Why can I not instantiate a class whose constructor is private in a friend class?

Обновить

April 2019

Просмотры

887 раз

16

У меня есть два класса; 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 ответы

17

Because you don't provide a constructor for Employee the braces in your initialization Employee emp{}; will perform an aggregate initialization, which essentially means that each member is initialized one-by-one using the default rules, in the context of main(). Since main() doesn't have access to the Salary constructor, it fails.

As others have pointed out, adding an Employee default constructor will resolve your problem:

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

You have to explicitly declare the default constructor of class Employee thus you can initialize an abject via uniform initialization:

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

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

}
2

You need Employee's ctor to call the ctor of Salary. The ctor of Salary is not accessible from main.

eg:

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

If you erase the "{}" after "Employee emp" in your main() function it compiles just fine (gcc 7.3.1 on Fedora 27).