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

时间:2021-08-18 15:16:23
回顾了下以前的学习笔记,看到如下说明


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的原则。

不知道大家如何看的,仁者见仁,智者见智!

14 个解决方案

#1


楼主多想了;所谓的private是是指其他的类或函数不能访问;但是排除了派生类;派生类并没有直接访问它;只是这个时候去构造基类;让基类去初始化;
 derived(const derived& rhs): base(rhs), y(rhs.y) {}
并没有访问基类的private;只能通过基类的函数去访问;

#2


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


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


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

如果说在复杂的继承关系中,子类的书写是不是还得充分考虑到基类的private区域?

#3


派生类包含了基类部分了
你sizeof下就明白了
派生类可以转换成基类也是有这部分的原因.



#4


我觉得子类在写copy构造函数的时候不用考虑父类的细节, 如果父类提供了copy构造函数可以这样
derived(const derived& rhs)     
  : base(rhs),y(rhs.y) {}

如果没有提供, 看看是不是不允许copy, 或者其他原因。 

#5


引用 3 楼 zmlovelx 的回复:
派生类包含了基类部分了 
你sizeof下就明白了 
派生类可以转换成基类也是有这部分的原因. 


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

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


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


但这个接口(如copy)设计成private,protected,只能 2选1了,那会出于 什么情况考虑呢?

#6


无定论.

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


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

#7


引用 6 楼 Jinhao 的回复:
无定论. 

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


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


恩 

大家不要太“语法”了。

大家继续!!

#8


或者说说在此问题上的  实际经验

#9


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

你只需要使用基类的构造函数来实现其数据的初始化,并没有违反OO的原则,private数据本意就是不提供直接访问,而是通过class提供结构进行访问.
基类的构造是你提供的接口,是可控的.

#10


lz在这里没有表述清楚吧

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

#11


引用 10 楼 Jinhao 的回复:
lz在这里没有表述清楚吧 

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


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

“显式地调用基类的拷贝构造函数” 是 否有必要?如果有,原因和目的是什么?

#12


其实大家都说了~


“可控性”


所以问题我觉得 已经解决


下面更多的想了解到和 分享下各自的经验

#13


唯一的义务就是通过基类的公有接口(或者有时候也是保护数据部分)在本类对象生成以前将其适当初始化。

#14


我觉得提供接口的目的不是不允许访问私有成员,而是让别人按照我的意图来访问私有成员。

#1


楼主多想了;所谓的private是是指其他的类或函数不能访问;但是排除了派生类;派生类并没有直接访问它;只是这个时候去构造基类;让基类去初始化;
 derived(const derived& rhs): base(rhs), y(rhs.y) {}
并没有访问基类的private;只能通过基类的函数去访问;

#2


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


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


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

如果说在复杂的继承关系中,子类的书写是不是还得充分考虑到基类的private区域?

#3


派生类包含了基类部分了
你sizeof下就明白了
派生类可以转换成基类也是有这部分的原因.



#4


我觉得子类在写copy构造函数的时候不用考虑父类的细节, 如果父类提供了copy构造函数可以这样
derived(const derived& rhs)     
  : base(rhs),y(rhs.y) {}

如果没有提供, 看看是不是不允许copy, 或者其他原因。 

#5


引用 3 楼 zmlovelx 的回复:
派生类包含了基类部分了 
你sizeof下就明白了 
派生类可以转换成基类也是有这部分的原因. 


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

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


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


但这个接口(如copy)设计成private,protected,只能 2选1了,那会出于 什么情况考虑呢?

#6


无定论.

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


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

#7


引用 6 楼 Jinhao 的回复:
无定论. 

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


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


恩 

大家不要太“语法”了。

大家继续!!

#8


或者说说在此问题上的  实际经验

#9


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

你只需要使用基类的构造函数来实现其数据的初始化,并没有违反OO的原则,private数据本意就是不提供直接访问,而是通过class提供结构进行访问.
基类的构造是你提供的接口,是可控的.

#10


lz在这里没有表述清楚吧

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

#11


引用 10 楼 Jinhao 的回复:
lz在这里没有表述清楚吧 

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


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

“显式地调用基类的拷贝构造函数” 是 否有必要?如果有,原因和目的是什么?

#12


其实大家都说了~


“可控性”


所以问题我觉得 已经解决


下面更多的想了解到和 分享下各自的经验

#13


唯一的义务就是通过基类的公有接口(或者有时候也是保护数据部分)在本类对象生成以前将其适当初始化。

#14


我觉得提供接口的目的不是不允许访问私有成员,而是让别人按照我的意图来访问私有成员。