正如其他人已经很好解释的那样,这完全符合 C++ 规则。 C++ 语言的关键设计假设是程序员知道自己在做什么:
C 可以很容易地射中自己的脚; C++ 让它变得更难,
但是当你这样做时,它会吹掉你的整条腿。
- Bjarne Stroustrup
在这里,您的设计有缺陷!您希望 B 从 A 继承(所以 B 是一个 A),但同时,您希望它不能像 A 一样使用(所以 B 毕竟不是真正的 A ):
class A {
public:
virtual void greet() { cout <<"Hello, I'm "<<this<<endl;}
virtual void tell() { cout<<"I talk !"<<endl; }
};
class B : public A {
private:
void greet() override { cout <<"Hello, I can tell you privatly that I'm "<<this<<" incognito"<<endl;}
};
人类可能会被这种自相矛盾的禁令所迷惑。 C++ 编译器认为你必须有充分的理由这样做,并按书行事:
A a;
a.greet(); // ok
B b;
b.greet(); // error: you said it was not accessible
A& b_as_a = b;
b_as_a.greet(); // ok: you said that A's interface had to be used
如果你想让 A 的公共函数不可访问,你应该使用非公共继承告诉编译器:
class C : protected A {
private:
void greet() override { cout <<"Hello, I can't tell you anything, but I'm "<<this<<endl;}
};
这意味着一个 C 是基于一个 A 实现的,但外界不应该知道它。这更干净:
C c;
c.greet(); // error, as for B
A& c_as_a = c; // ouch: no workaround: because the A inheritance is procteted
通常,如果您想重用 A 的特性来构建具有完全不同接口的 C 类,您会使用这种继承。是的,如果你问的话,C++ 可以强制执行更严格的规则:-)。
通常,您会公开完全不同的功能。但是,如果您想使用 A 的公共功能之一以方便起见,这很容易:
class C : protected A {
private:
void greet() override { cout <<"Hello, I can't tell you anything, but I'm "<<this<<endl;}
public:
using A::tell; // reuse and expose as it is
};