因为我觉得C ++中的受保护的私有继承感觉不太舒服,所以我搜索了它并得出了这个stackoverflow答案:Difference between private, public, and protected inheritance。 太好了!我想,让我们试一试。所以我编写了一个小例子程序来测试它,并将exptected输出写为注释。
class Person{
public: virtual void publicInterface() {}
protected: virtual void protectedInterface() {}
private: virtual void privateInterface() {}
};
class Professor : public Person {};
class Teacher : protected Person {
public: void teachPublic(){publicInterface();}
public: void teachProtected(){protectedInterface();}
public: void teachPrivate(){privateInterface();} // not compiling
};
class Student : private Person {
public: void learnPublic(){publicInterface();}
public: void learnProtected(){protectedInterface();}
public: void learnPrivate(){privateInterface();} // not compiling
};
int main()
{
Person* p = new Person(); // ok is-a
Person* pro = new Professor(); // ok is-a
Person* t = new Teacher(); // not compiling! No is-a relat.
Person* s = new Student(); // not compiling! No is-a
Teacher* t2 = new Teacher(); // ok
Student* s2 = new Student(); // ok
pro->publicInterface(); // ok
t2->publicInterface(); // not compiling
s2->publicInterface(); // not compiling
t2->teachPublic(); // ok
t2->teachProtected(); // ok
t2->teachPrivate(); // not compiling
s2->learnPublic(); // ok
s2->learnProtected(); // not compiling <-- compiles, but why?
s2->learnPrivate(); // not compiling
}
运行它确实完全符合我的预期。但是,最后一行似乎是编译的 - 这有点没有从所描述的私有继承行为中删除。
有人知道为什么要编译吗?
答案 0 :(得分:0)
方法learnProtected
是公开的。因此它可以从外面打电话#34; (即通过s2
)。
方法protectedInterface
受到保护,这意味着它只能由Person
的成员和朋友或来自Person
的任何类的成员访问。 Student
类派生自Person
,因此learnProtected
可以调用protectedInterface
。
它私有地继承自Person
这一事实只会影响Base类和成员的外部可见性。无论使用哪种继承(私有,受保护,公共),Student
本身都可以访问Person
的任何公共或受保护成员。
答案 1 :(得分:0)
我现在有一个例子,它向我解释了私有继承的行为:
class Person{
public: virtual void publicInterface() {}
protected: virtual void protectedInterface() {}
private: virtual void privateInterface() {}
};
class Professor : public Person {};
class Teacher : protected Person {
public: void teachPublic(){publicInterface();}
void teachProtected(){protectedInterface();} // ok!
void teachPrivate(){privateInterface();} // not compiling
};
class Student : private Person {
public: void learnPublic(){publicInterface();}
void learnProtected(){protectedInterface();} // ok!
void learnPrivate(){privateInterface();} // not compiling
};
class TA : public Teacher {
public: void correctExercises(){publicInterface();}
};
class Child : public Student {
public: void play(){publicInterface();} //NOT working, since we priva
};
int main()
{
Person* p = new Person(); // ok is-a
Person* pro = new Professor(); // ok is-a
Person* t = new Teacher(); // not compiling! No is-a relat.
Person* s = new Student(); // not compiling! No is-a
Teacher* t2 = new Teacher(); // ok
Student* s2 = new Student(); // ok
pro->publicInterface(); // ok
t2->publicInterface(); // not compiling
s2->publicInterface(); // not compiling
t2->teachPublic(); // ok
t2->teachProtected(); // ok
t2->teachPrivate(); // not compiling
s2->learnPublic(); // ok
s2->learnProtected(); // ok! learnProteted is public
s2->learnPrivate(); // not compiling
TA* ta = new TA(); // ok
Child* c = new Child(); // ok
ta->correctExercises(); // ok
c->play(); // ok however call inside play not ok!
}
但我仍然觉得这很模糊......在现实世界中没有人能真正想出这样的设计,对吗?
答案 2 :(得分:-2)
函数Person :: learnProtected()在Student类中不可见,因此当您声明Student :: learnProtected()时,编译器将其理解为不覆盖声明。
您可以确保添加约束&#34;覆盖&#34;对于Student :: learnProtected(),当函数没有覆盖父虚函数时,编译器将显示错误:
const dbHandler = require('dbHandler');
app.get('/blogs/all',function(req,res,next){
Blog.find({},dbHandler(res));
});
这会导致编译错误:
C3668&#39;学生:: learnProtected&#39;:方法,使用覆盖说明符&#39;覆盖&#39;没有覆盖任何基类方法ConsoleApplication3