2011-09-05 79 views
8

下面的简单的例子会产生一个编译错误,因为我无意中使用私有继承:指向基础类和私有继承

main.cpp中:21:错误:“A”是B的”不可访问的基“

class A 
{ 


}; 

class B : /*ups forgot that -> public*/ A 
{ 


}; 

int main(int , char *[]) 
{ 
    A* test = new B; 

    return 0; 
} 

你能不能帮我解释一下究竟是在基类交通不便,为什么需要从B*A*转换?

+1

[什么是访问说明?我应该继承与私人,保护或公共?](http://stackoverflow.com/questions/5447498/what-are-access-specifiers-should-i-inherit-with-private-protected-or-public/%5d )对你来说是一个很好的阅读。 –

+1

也这个链接也许有用http://www.gotw.ca/publications/mill06.htm –

回答

10

私有继承意味着任何人,除B(和B的朋友),B不是从A派生

+0

你能解释一下,在功能层面的'构造函数?由于私人继承,哪些功能是不可访问的? –

+0

@Ronald:整个班级无法进入,包括所有构造函数和其他成员。什么都无法访问。 –

+0

但是,如果'A类'完全无法访问,为什么我可以创建'B类'呢?对不起,我很困惑:-) –

0

由于B从A继承,A的默认构造函数将B的构造函数之前调用但是因为它是私有的并且不会继承到B,所以会出现编译器错误。

1

转换B*A*是不可访问的,因为基类子对象是私人。当您将B*转换为A*时,您将返回指向基类子对象的指针。后者必须可以访问,以便转换可以访问。在B的朋友的任何功能转换变得可访问。顺便说一句,您可以随时通过显式转换访问转换。

A* p = (A*)(new B); 

注意,在某些情况下,只可访问的变换是必须的,但在某些情况下,要求AB公共(强于访问)的基础。例如,当你试图抓住B类型的异常与catch(A&) - 它要求A公共基类的B

+0

你提到的显式演员,它在功能上与'reinterpret_cast'相同吗?从编译器的角度来看,你的意思是转换两个完全不相关的类型? –

+0

@Ronald:为了完美,我不确定。在标准中,这些示例使用C风格的演员而不提及它是哪个演员。你可以通过编写static_cast来尝试。如果它有效,那么它是static_cast,否则它是reinmenpret_cast –

+0

Armen,感谢您的帮助。 –

7

Could you help me and explain what exactly is inaccessible in the base class and why it is needed in the conversion from B* to A*?

Ouside的BB的朋友,这个简单的事实BA是不可见的。这不是隐藏成员变量或成员函数,而是隐藏关系本身。这是main为什么你不能用一个指针Anew B结果绑定,因为据main而言,B不是A(因为你不能这样做A * p = new unrelated;方法相同)

至于为何它是完全相同的答案:因为没有访问关系,编译器不知道(嗯,它知道,但不会告诉你)如何获得B内的A主题的指针,因为到目前为止因为在此情况下可以看到,AB根本没有关系。

+0

谢谢大卫,非常好的解释。我想我现在明白了:-) –

0

由于参考指针基类的不能指向继承类的反对,这是否意味着保护和私有继承无关多态性?

0

公共/私人遗产是相当于公共/私人成员变量。

转换的结果是对派生类对象的基类子对象的引用。

我认为可访问性意味着派生类对象的基类子对象的可访问性。对于客户端,只有在我们使用公共继承时,才能访问基类子对象。对于派生类的成员函数,无论我们使用public/protected/privaye继承,基类子对象是可访问的。

class A{ 

}; 

class B: private A{ 
private: 
    int* m_pb; 
public: 
    B(){m_pb=new int(10)}; 
    void func() 
    { 
     A* pa= new B;  //OK 
     int *pmb = m_pb; //OK 
    } 

}; 
int main() 
{ 
    B* pb = new B; 
    A* pa= pb;    // inaccessible 
    int *pmb = pb->m_pb; // inaccessible 
} 

OK.I表示公共/私有继承等同于公共/私有成员变量。

参考: http://pic.dhe.ibm.com/infocenter/ratdevz/v8r5/index.jsp?topic=%2Fcom.ibm.tpf.toolkit.compilers.doc%2Fref%2Flangref_os390%2Fcbclr21011.htm