基类的private成员变量,子类有义务为其做初始化工作么?

xxgamexx 2009-04-18 02:38:30
回顾了下以前的学习笔记,看到如下说明


class base {
public:
base(int initialvalue = 0): x(initialvalue) {}
base(const base& rhs): x(rhs.x) {}

private:
int x;
};

class derived: public base {
public:
derived(int initialvalue)
: base(initialvalue), y(initialvalue) {}

derived(const derived& rhs) // 错误的拷贝
: y(rhs.y) {} // 构造函数

private:
int y;
};



这里的“错误”之处在于,拷贝构造函数没有顾及到基类private变量:x.. 得出的结论是“派生类必须同时要顾及到父类初始化变量”。
正确的做法是:

class derived: public base {
public:
derived(const derived& rhs): base(rhs), y(rhs.y) {}

...

};



但现在来看,却有很大的疑问了。

从语义上来说private的语义就是私有的,基类之所以把x设定为private的初衷就是想“据为己有”,即便是子类也不允许访问。而以上的说法似乎破坏了当初的“原则”,强制去访问了private,破坏了当初的“意图”了。所以我现在认为这却是不可取的。已经破坏了OO的原则。

不知道大家如何看的,仁者见仁,智者见智!
...全文
314 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
damo_xu 2009-04-18
  • 打赏
  • 举报
回复
我觉得提供接口的目的不是不允许访问私有成员,而是让别人按照我的意图来访问私有成员。
adventurelw 2009-04-18
  • 打赏
  • 举报
回复
唯一的义务就是通过基类的公有接口(或者有时候也是保护数据部分)在本类对象生成以前将其适当初始化。
xxgamexx 2009-04-18
  • 打赏
  • 举报
回复
其实大家都说了~


“可控性”


所以问题我觉得已经解决


下面更多的想了解到和分享下各自的经验
xxgamexx 2009-04-18
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 Jinhao 的回复:]
lz在这里没有表述清楚吧

"基类的private成员变量,子类有义务为其做初始化工作么?"
意思是,子类是否有义务在拷贝构造函数中 显式地调用基类的拷贝构造函数.而不是说去违背反问控制的规则去访问基类的私有成员.
[/Quote]

其实我更想问的是
在实际的设计中

“显式地调用基类的拷贝构造函数” 是否有必要?如果有,原因和目的是什么?
Jinhao 2009-04-18
  • 打赏
  • 举报
回复
lz在这里没有表述清楚吧

"基类的private成员变量,子类有义务为其做初始化工作么?"
意思是,子类是否有义务在拷贝构造函数中 显式地调用基类的拷贝构造函数.而不是说去违背反问控制的规则去访问基类的私有成员.
  • 打赏
  • 举报
回复
从语义上来说private的语义就是私有的,基类之所以把x设定为private的初衷就是想“据为己有”,即便是子类也不允许访问。而以上的说法似乎破坏了当初的“原则”,强制去访问了private,破坏了当初的“意图”了。所以我现在认为这却是不可取的。已经破坏了OO的原则。

你只需要使用基类的构造函数来实现其数据的初始化,并没有违反OO的原则,private数据本意就是不提供直接访问,而是通过class提供结构进行访问.
基类的构造是你提供的接口,是可控的.
xxgamexx 2009-04-18
  • 打赏
  • 举报
回复
或者说说在此问题上的 实际经验
xxgamexx 2009-04-18
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 Jinhao 的回复:]
无定论.

从语法上说,那"错误的构造函数"是正确的.


>>这里的“错误”之处在于,拷贝构造函数没有顾及到基类private变量:x.. 得出的结论是“派生类必须同时要顾及到父类初始化变量”。
在实际情况下,这与类体系的设计有关, 有的基类并不要求派生类的拷贝构造函数在初始化基类的时候用基类的拷贝构造函数去初始化
[/Quote]



大家不要太“语法”了。

大家继续!!
Jinhao 2009-04-18
  • 打赏
  • 举报
回复
无定论.

从语法上说,那"错误的构造函数"是正确的.


>>这里的“错误”之处在于,拷贝构造函数没有顾及到基类private变量:x.. 得出的结论是“派生类必须同时要顾及到父类初始化变量”。
在实际情况下,这与类体系的设计有关, 有的基类并不要求派生类的拷贝构造函数在初始化基类的时候用基类的拷贝构造函数去初始化
xxgamexx 2009-04-18
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 zmlovelx 的回复:]
派生类包含了基类部分了
你sizeof下就明白了
派生类可以转换成基类也是有这部分的原因.
[/Quote]

CSDN回答的人就是有速度 呵呵

恩,sizeof是可以看出来,但是用sizeof是说明不了问题的,我想从OO的思想上来讨论这个问题 呵呵


4楼说的有点道理,设计基类的这个人如果公开了某个接口(如你说的copy),可能是有他的目的或者其他隐含的原因。


但这个接口(如copy)设计成private,protected,只能2选1了,那会出于什么情况考虑呢?
liqinghua1653 2009-04-18
  • 打赏
  • 举报
回复
我觉得子类在写copy构造函数的时候不用考虑父类的细节, 如果父类提供了copy构造函数可以这样
derived(const derived& rhs)
: base(rhs),y(rhs.y) {}

如果没有提供, 看看是不是不允许copy, 或者其他原因。
帅得不敢出门 2009-04-18
  • 打赏
  • 举报
回复
派生类包含了基类部分了
你sizeof下就明白了
派生类可以转换成基类也是有这部分的原因.



xxgamexx 2009-04-18
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 mengde007 的回复:]
楼主多想了;所谓的private是是指其他的类或函数不能访问;但是排除了派生类;派生类并没有直接访问它;只是这个时候去构造基类;让基类去初始化;
derived(const derived& rhs): base(rhs), y(rhs.y) {}
并没有访问基类的private;只能通过基类的函数去访问;
[/Quote]

“但是排除了派生类”,这个有什么标准或者依据的么?


我觉得从语义上来说,是有的阻塞的。

如果说在复杂的继承关系中,子类的书写是不是还得充分考虑到基类的private区域?
mengde007 2009-04-18
  • 打赏
  • 举报
回复
楼主多想了;所谓的private是是指其他的类或函数不能访问;但是排除了派生类;派生类并没有直接访问它;只是这个时候去构造基类;让基类去初始化;
derived(const derived& rhs): base(rhs), y(rhs.y) {}
并没有访问基类的private;只能通过基类的函数去访问;

64,644

社区成员

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

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