关于私有继承的一个问题

lilingcx 2010-10-26 11:49:48
最近研究私有继承,书上说私有继承的情况下,子类的指针或者索引,必须通过显示转化的方式,才能向上类型转化成父类的指针或者索引. 所以我写了个测试,在VS2005上进行演示,发现一些问题,百思不得其解.

代码:

class Test
{
};

class TestPublic : public Test
{
};

class TestPrivate : private Test
{
public:
void setA(TestPrivate *test)
{Test *a=test;}; //问题1, 为什么在子类的方法中,向上类型转化不需要显示?

void setB(TestPrivate test)
{Test b=test;};

void setC(TestPrivate test)
{Test& c=test;};
};

TestPublic testPublic; //先验证public继承下,向上类型转化的情况
Test A = testPublic; //成功,这边其实是验证Test的默认拷贝构造函数Test(const Test&)中会发生的向上类型转化
Test& B = testPublic; //成功
Test* C = &testPublic; //成功

TestPrivate testPrivate; //验证public继承下,隐式向上类型转化的情况
Test A = testPrivate; //失败
Test& B = testPrivate; //失败
Test* C = &testPrivate; //失败

TestPrivate testPrivate; //验证public继承下,显示向上类型转化的情况
Test A = (Test&)testPrivate; //成功
Test& B = (Test&)testPrivate; //成功, 这个验证了书上的说法是正确的,必须显示转化
Test* C = (Test*)&testPrivate; //成功

所以问题总结如下
1) 私有继承下, 子类的方法中向上类型转化是不要显示的,但在外部必须是显示的,这是为什么?

...全文
301 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
无尽大海 2010-10-27
  • 打赏
  • 举报
回复
学习,LZ很喜欢思考!学习。。。
lilingcx 2010-10-26
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 hai040 的回复:]

觉得只是规定,为了安全性考虑
[/Quote]

这应该就是个规定,那么为何由来这个规定,它为了避免什么样的问题?
lilingcx 2010-10-26
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 colorfulcode 的回复:]

基类的对外可见性由派生类继承的方式而定

test 是TestPrivate 私有部分,所以 Test& B = testPrivate;搞不成

因为私有东西对内部成员或者友员是可见的,所以Test *a=test有搞头
[/Quote]

基类的对外可见性和类的向上转换有什么必然关系吗? 如果这样,那么只要显示的转换,就能改变基类的对外可见性了?
hai040 2010-10-26
  • 打赏
  • 举报
回复
觉得只是规定,为了安全性考虑
qq120848369 2010-10-26
  • 打赏
  • 举报
回复
不知道这有什么可测试的,这和权限有联系么.

private继承来的意思就是基类本身就是个全部private的类而已,别再想截取基类部分使用了.
colorfulcode 2010-10-26
  • 打赏
  • 举报
回复
基类的对外可见性由派生类继承的方式而定

test 是TestPrivate 私有部分,所以 Test& B = testPrivate;搞不成

因为私有东西对内部成员或者友员是可见的,所以Test *a=test有搞头
xspace_time 2010-10-26
  • 打赏
  • 举报
回复
基础很难学,还是先学点是用的吧
無_1024 2010-10-26
  • 打赏
  • 举报
回复
学习ing
Ethan_Hu 2010-10-26
  • 打赏
  • 举报
回复
应该说这种关系可以在其直接子类的方法或友元中体现出来。若是保护继承,那么这种关系就能扩充到更下层的
子类,若是公有继承,那就是完全的不受限的 is-a 了。
Ethan_Hu 2010-10-26
  • 打赏
  • 举报
回复
不要搞错了,has-a专指组合关系,或者称为包含。
私有继承严格来是一个受限的 is-a 关系,它面向的目标是其直接子类的方法或friend。
lilingcx 2010-10-26
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 gules 的回复:]

在C++中,我个人认为正确的观念应该是:凡用到继承就应该是在“多态”场景下(极特殊的情况不考虑)。

那么,C++中多态一般有两个场景:一是为外界(客户端、使用类体系者)提供多态(公有继承),它建模的是“是一个”的关系;二是受控多态(内部使用,保护或私有继承),它建模的是“依……实现”的关系。

只有公有继承才是“是一个”的关系,因此在外界看来,此时的派生类才“是一个”基类,派生类指针或……
[/Quote]

你的说法让我有种豁然开朗的感觉. 隐式的向上转换是一个"自然的"转换,其目的也就是为了更好的支持"多态",但私有继承的目的主要是为了实现has-a的关系,而并非多态,所以就不好再用这种"自然的"转化. 所以C++在这里提及需要显示转化,主要原因还是思想延续和语言实现上面的考虑,而并非什么"大是大非"的问题.
不知道这样理解是否正确?
lilingcx 2010-10-26
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 dingshaofengbinbin 的回复:]

如果是私有继承的话向上转换是没有意义的,因为由于都是私有的,你转换之后是不能调用任何东西的。所以编译器禁止了!!!
[/Quote]

没有完全看明白, 这里的"私有"是基类的所有方法与成员,都变成了派生类私有方法和成员吗? 那么转换后后不能调用任何东西是指什么? 是说转换后基类的指针(引用)不能调用派生类的?
1)从基类继承来的方法?
2)override基类的某个方法?
3)其他?
dingshaofengbinbin 2010-10-26
  • 打赏
  • 举报
回复
给楼主一个建议:这样的怀疑精神是值得赞赏的,但是要学会分析,就拿这一题来讲,如果你不知道为什么的话,首先要想一想,如果不这样的话,会带来什么样的后果;如果这样的话,又有什么样的好处;他有没有必要存在等等。就是一个不断问自己的过程,我猜想你可能没有这样问过自己吧!!
Ethan_Hu 2010-10-26
  • 打赏
  • 举报
回复
继承方式并不影响直接子类的访问权限。
class B {
public:
~B () {}
void g () const {}
};

class D : B { // 继承方式对可见性的影响只针对更下层类及外部 client
public:
void f () const {
g (); // 以前能访问的现在还是一样。
const B *p = this;
}
};
dingshaofengbinbin 2010-10-26
  • 打赏
  • 举报
回复
如果是私有继承的话向上转换是没有意义的,因为由于都是私有的,你转换之后是不能调用任何东西的。所以编译器禁止了!!!
taodm 2010-10-26
  • 打赏
  • 举报
回复
楼主喜欢思考,这很好,但是过度的思考就未必是好事了。
为啥过欧几里德选择“一点只能作一条直线的一条平行线”作为欧几里德几何的最根本公理?
你现在的问题类似了。
gules 2010-10-26
  • 打赏
  • 举报
回复
在C++中,我个人认为正确的观念应该是:凡用到继承就应该是在“多态”场景下(极特殊的情况不考虑)。

那么,C++中多态一般有两个场景:一是为外界(客户端、使用类体系者)提供多态(公有继承),它建模的是“是一个”的关系;二是受控多态(内部使用,保护或私有继承),它建模的是“依……实现”的关系。

只有公有继承才是“是一个”的关系,因此在外界看来,此时的派生类才“是一个”基类,派生类指针或引用(因为C++中只有通过指针或引用才能达成多态)才“自然的”转换为基类指针或引用;保护或私有继承不是“是一个”的关系,所以在外界看来,它们不能自然的转换,但在派生类内部,为使用多态性(受控的),这种转换就是必要的了,所以C++允许并自动在派生类内部进行这种转换(也是语言的规定)。
Jim_King_2000 2010-10-26
  • 打赏
  • 举报
回复
私有继承并不想继承基类的接口。也就是说,私有继承不表达isA的关系,因此无法与基类指针替换使用。lz也不要在继承类内部使用基类指针。

私有继承要表达的语义是hasA。它与包含的区别主要有以下几点(摘录自《Exceptional C++》):
1、需要访问基类protected成员。
2、需要override某些成员函数。
3、需要优先构造或者最后销毁某些对象。
4、需要共享某些虚基类。
5、需要空类优化。

64,642

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧