C++ 类继承错误:私有成员

C++ 类继承错误:私有成员,c++,class,inheritance,parent,private,C++,Class,Inheritance,Parent,Private,我有一个基类/父类:Person 和两个子类/子类:Player、Coach 这是基类Person的标题的外观: class Person { public: Person(string name); Person(); virtual ~Person(); string getName(); void setName(string name); virtual void printSpec(

我有一个基类/父类:Person

和两个子类/子类:Player、Coach

这是基类Person的标题的外观:

class Person
{
    public:
        Person(string name);
        Person();
        virtual ~Person();
        string getName();
        void setName(string name);
        virtual void printSpec() const = 0;

    private:
        string name;
};
我试着编译并运行,它开始抱怨:

include\Person.h||In constructor 'Coach::Coach(std::string, std::string)':|
include\Person.h|19|error: 'std::string Person::name' is private|
\src\Coach.cpp|5|error: within this context|
||=== Build finished: 2 errors, 0 warnings ===|
并指出:

private:
    string name;
在子类“Coach”的两个构造函数之一的上下文中:

但是,它并没有对“Player”类的构造函数中的同一行发出相同的抱怨,只抱怨“Coach”类的构造函数中的“string name是私有成员”

我为其他人查找了一些解决方案,尝试了保护而不是私有,尝试了更改变量的名称,但没有任何用处


提供什么?

将“private”更改为“protected”private意味着系统的其他部分(包括派生类)无法访问该成员。

派生类无法访问
private
成员

解决方案可以是使用成员初始化列表来执行此操作:

Coach::Coach(string name, string responsibility): Person(name){
    //                                            ^^^^^^^^^^^^
    //                     Initialize the name through the base class constructor
    this->responsibility = responsibility;
}
因为
Person
是基类,并且有一个使用名称的构造函数,所以可以这样做。您不需要从派生类访问
名称
成员


另一个解决方案是将此成员设置为受保护的(第一个解决方案更好)

您可以看一下,继承部分讨论访问类型


不是为了回答这个问题,而是为了获得一些好的实践,我建议您将
string
参数作为
const
参考传递。这是一个:


name
在基类中是私有的,因此不能从派生类访问它。
假设Coach公开地从Person派生,您可以使成员变量受到保护,但幸运的是,
Person
构造函数使用了一个名称,因此您不需要直接从派生类访问它。您可以使用初始化列表,因此不需要设置两次

Coach::Coach(string name, string responsibility)
                   : Person(name){
                 //  ^^^^^^^^^^^^
                 // Sends name to Person's constructor
    this->responsibility = responsibility;
}

如果您已经在Coach构造函数中调用Person(name),那么为什么需要设置此->name?我猜是由Person::Person负责的?在任何情况下,受保护的作用域都应该起作用。获取一个
Player::name
是私有的。如果您希望派生类具有成员级访问权限(在本例中没有理由,但那是另一回事),则需要对其进行保护或公开或朋友级访问(后者对于派生类来说非常罕见)。如何声明Coach类?(别忘了在那里也使用公开的词)我现在可以用protected,谢谢。我已经得到了一些示例代码,它有私有成员和两个子类,它们可以顺利地使用该成员。或者我一定是错过了一些让它运行起来的技巧,或者可能是它都是预编译的。不管怎样,问题现在解决了。不要让它受到保护。
Person
的构造函数将初始化它。
Coach
不需要公开派生;只要
Person
是基类,就可以在初始值设定项列表中初始化它。
Coach
是从
Person
派生的,因此构造函数是正确的方法。将
名称
更改为
受保护
是错误的。构造函数可以初始化成员,如果需要,可以使用
setName
member函数在以后设置它。@PeteBecker你说得对,我编辑了我的文章以使其更合适。感谢您指出这一点。不要将其更改为受保护。
Person
的构造函数初始化
name
,如果需要,
setName
成员函数会对其进行更改。没有理由在此处使用
受保护的
。同意。我只是在说“为什么编译器会产生错误”。使用访问器方法(在本例中)比使用protected更好。
class Person
{
    public:
        Person(string name);
        Person();
        virtual ~Person();
        string getName();
        void setName(string name);
        virtual void printSpec() const = 0;

    protected:
//  ^^^^^^^^^
        string name;
};
Coach::Coach(const string& name, const string& responsibility): Person(name){
    //       ^^^^^       ^       ^^^^^       ^
    this->responsibility = responsibility;
}
Coach::Coach(string name, string responsibility)
                   : Person(name){
                 //  ^^^^^^^^^^^^
                 // Sends name to Person's constructor
    this->responsibility = responsibility;
}