【问题标题】:Class inheritance error: Private member类继承错误:私有成员
【发布时间】:2013-08-30 11:01:20
【问题描述】:

我有一个基类/父类: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”的两个构造函数之一的上下文中:

Coach::Coach(string name, string responsibility): Person(name){
    this->name = name;
    this->responsibility = responsibility;
}

但是,它并没有对“Player”类的构造函数中的同一行提出同样的抱怨,只抱怨“Coach”类的构造函数中的“字符串名称是私有成员” .

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

什么给了?

【问题讨论】:

  • 如果您已经在 Coach 构造函数中调用了 Person(name),为什么还需要设置 this->name?我假设 Person::Person 会处理这个问题?在任何情况下,受保护的范围都应该起作用。
  • 获取decent book on C++Player::name 是私人的。如果您希望派生类具有成员级别的访问权限(在这种情况下没有理由这样做,但那是另一回事),则需要 protectedpublic 或 friend-ed(后者对于派生类非常不寻常)。
  • 如何声明 Coach 类? (不要忘记在其中也使用公共词)
  • 我现在可以在受保护的情况下使用它,谢谢。我有一些示例代码,它有私有成员和两个子类,它们可以顺利使用该成员。或者我一定是错过了一些技巧来让它全部工作,或者它可能都是预编译的。无论如何,现在问题解决了。
  • 不要对其进行保护。 Person 的构造函数将初始化它。

标签: c++ class inheritance parent private


【解决方案1】:

派生类无法访问private 成员。

解决方案可能是使用 member-initialization-list 来做到这一点:

Coach::Coach(string name, string responsibility): Person(name){
    //                                            ^^^^^^^^^^^^
    //                     Initialize the name through the base class constructor
    this->responsibility = responsibility;
}

因为Person基类 并且有一个带有名称的构造函数,所以您可以这样做。您不需要从派生类访问name 成员。


另一种解决方案可能是设置此成员protected第一个解决方案更好)。

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

    protected:
//  ^^^^^^^^^
        string name;
};

大家可以看看here,继承部分讲access-type。


不回答这个问题,但为了一些好的做法,我建议您将string 参数作为const 参考传递。这是一个better practice

Coach::Coach(const string& name, const string& responsibility): Person(name){
    //       ^^^^^       ^       ^^^^^       ^
    this->responsibility = responsibility;
}

【讨论】:

  • Coach 派生自Person,所以构造函数是正确的方法。将name 更改为protected错误。构造函数可以初始化成员,以后如果需要可以使用setName成员函数来设置。
  • @PeteBecker 你是对的,我编辑了我的帖子以使其更合适。感谢您指出这一点。
【解决方案2】:

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

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

【讨论】:

  • Coach 不需要公开派生;只要Person是基类,就可以在初始化列表中初始化。
【解决方案3】:

将“私有”更改为“受保护”私有意味着系统的其他部分(包括派生类)不能访问该成员。

【讨论】:

  • 不要将其更改为受保护。 Person 的构造函数初始化name,如果需要,setName 成员函数会更改它。这里没有理由使用protected
  • 同意。我只是在解决“为什么编译器会产生错误”。使用访问器方法(在这种情况下)比受保护更好。
猜你喜欢
  • 1970-01-01
  • 2013-02-12
  • 2020-09-04
  • 2020-09-01
  • 2018-05-11
  • 1970-01-01
  • 2015-01-21
  • 2011-09-26
  • 2011-02-10
相关资源
最近更新 更多