C++ 类继承错误:私有成员
我有一个基类/父类:Person 和两个子类/子类:Player、Coach 这是基类Person的标题的外观: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(
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;
}