Почему я не могу создать экземпляр класса, конструктор которого является закрытым в другом классе? - PullRequest
18 голосов
/ 24 апреля 2019

У меня есть два класса; Salary, предназначенный для хранения информации и расчетов по заработной плате сотрудника, и Employee с объектом типа class Salary и некоторыми членами, такими как имя и адрес сотрудника ...

  • Я хочу предотвратить создание экземпляра class Salary, за исключением class Employee. Поэтому я объявил конструкторы Salary закрытыми и сделал Employee другом Salary. Но я получаю ошибки:

    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
    }
    
  • Проблема исчезнет, ​​если я перейду объявить main:

    int main(int, char*[]);
    

    И сделайте main другом class Salary, например, в Зарплате:

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

Теперь программа правильно компилируется!

*** Другое дело, если я объявлю объект таким образом:

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

Ответы [ 4 ]

18 голосов
/ 24 апреля 2019

Поскольку вы не предоставляете конструктор для Employee фигурных скобок при инициализации Employee emp{}; будет выполнять совокупную инициализацию , что, по сути, означает, что каждый элемент инициализируется один за другим с использованиемправила по умолчанию, в контексте main().Поскольку main() не имеет доступа к конструктору Salary, происходит сбой.

Как отмечали другие, добавление конструктора Employee по умолчанию решит вашу проблему:

class Employee {
    public:
        Employee() = default;
        std::string name_;
        Salary sal;
};
3 голосов
/ 24 апреля 2019

Вам нужен Employee ctor, чтобы вызвать ctor Salary. Ctor Salary не доступен с main.

например:

class Employee {
public:
    Employee() : sal() {}
    public:
        std::string name_;
        Salary sal;
};
3 голосов
/ 24 апреля 2019

Вы должны явно объявить конструктор по умолчанию класса Employee, таким образом, вы можете инициализировать объект с помощью uniform initialization:

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

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

}
1 голос
/ 24 апреля 2019

Если вы удалите «{}» после «Employee emp» в своей функции main (), она будет прекрасно скомпилирована (gcc 7.3.1 в Fedora 27).

...