web-dev-qa-db-fra.com

Pourquoi ne puis-je pas instancier une classe dont le constructeur est privé dans une classe amie?

J'ai deux classes; Salary qui est destiné à contenir des informations et des calculs concernant le salaire d'un employé et Employee qui a un objet de type class Salary et certains membres comme le nom et l'adresse de l'employé ...

  • Ce que je veux faire, c'est empêcher class Salary d'être instancié sauf par class Employee. J'ai donc déclaré les constructeurs de Salary privés et fait de Employee un ami de Salary. Mais je reçois des erreurs:

    class Employee;
    
    class Salary {
        public:
    
        private:
            Salary() : revenue_{}, cost_{} {}
            Salary(int x, int y) : revenue_{ x },
            cost_{ y } {
    
            }
            int revenue_, cost_;
            friend class Employee;
    };
    
    class Employee {
        public:
            std::string name_;
            Salary sal;
    };
    
    int main(){
    
        Employee emp{}; // "Salary::Salary()" is inaccessible
    }
    
  • Le problème disparaît si je déclare en avant main:

    int main(int, char*[]);
    

    Et faites de main un ami de class Salary comme ça dans le salaire:

    class Salary {
        //...
        friend int main(int argc, char* argv[]);
    };
    

Maintenant, le programme se compile correctement!

*** Une autre chose principale si je déclare un objet de cette façon:

Employee emp; // ok
Employee emp{}; // error?
18
Syfu_H

Parce que vous ne fournissez pas de constructeur pour Employee, les accolades de votre initialisation Employee emp{}; Effectueront une initialisation agrégée , ce qui signifie essentiellement que chaque membre est initialisé un par un -une utilisant les règles par défaut, dans le contexte de main(). Puisque main() n'a pas accès au constructeur Salary, il échoue.

Comme d'autres l'ont souligné, l'ajout d'un constructeur par défaut Employee résoudra votre problème:

class Employee {
    public:
        Employee() = default;
        std::string name_;
        Salary sal;
};
18
zdan

Vous devez déclarer explicitement le constructeur par défaut de la classe Employee ainsi vous pouvez initialiser un abject via uniform initialization:

class Employee {
    public:
        Employee(){} // add it
        std::string name_;
        Salary sal;
};

int main(){
    Employee emp{}; // now this should compile

}
3
Raindrop7

Vous avez besoin du ctor de Employee pour appeler le ctor de Salary. Le ctor de Salary n'est pas accessible depuis main.

par exemple:

class Employee {
public:
    Employee() : sal() {}
    public:
        std::string name_;
        Salary sal;
};
3
schuess

Si vous effacez le "{}" après "Employee emp" dans votre fonction main (), il se compile très bien (gcc 7.3.1 sur Fedora 27).

1
Eric Sokolowsky