我有以下假设代码:
class Base {
public:
virtual void print() {
std::cout << "Base\n";
}
// assume virtual destructor
};
class Derived : private Base {
public:
void print() {
std::cout << "Derived\n";
}
};
int main() {
// Derived d{}; works fine
Base *pd = new Derived{}; // doesn't work
pd->print();
// assume memory is deallocated
}
起初,我认为它会起作用,因为构造函数无论如何都不会被继承。但是编译器给出了错误:
错误:&#39; Base&#39;是一个无法访问的&#39; Derived&#39;
我无法弄清楚到底发生了什么?
答案 0 :(得分:4)
这是一个很好的猜测,但问题不在于构造函数或成员函数。
在第
行Base *pd = new Derived{}; // doesn't work
编译器隐式地将右侧new Derived{}
(类型为Derived*
)转换为类型Base*
。
标准用于描述何时可以将指向派生类的指针隐式转换为指向基类的指针的术语是 accessibility 。从第11.2 / 5小节:
如果可以访问基类,可以隐式地将指向派生类的指针转换为指向该基类的指针
列出了一些技术条件(11.2 / 4,如果你真的关心的话)可以使基类可访问,但Base不会满足这些条件。
简短版本是,private
继承隐藏基类,访问说明符private
需要public
才能编译代码。希望有所帮助。
答案 1 :(得分:1)
您私下导出Base
,这就是您收到错误的原因。
使用私有继承,基类中的所有成员都将作为私有继承。这意味着私人成员保持私密,受保护的公共成员变得私密。这就是为什么你无法在print()
编译器中使用main
的原因,无法将derived
指针转换为base
类型,因为继承是私有的。
答案 2 :(得分:0)
在隐藏派生类内部知识的上下文中(IE非朋友,而不是派生自Derived的类),似乎两个类之间没有关系。
当您尝试分配基类型的指针时,您要将此Derived指针转换为Base指针。由于继承是隐藏的,就像您尝试将其分配给不相关类型的指针一样。但是编译器确实知道它是相关的,所以它不是仅仅给你一个无用的错误,而是告诉你你正在尝试做的转换是不可访问的。