再谈C++中的has-a关系(通过复合塑模出has-a 明智而审慎地使用Private继承)

本文探讨了C++中has-a关系的实现方式,包括使用包含和私有继承。详细对比了两者在实现细节上的差异,如成员访问权限、构造函数调用方式等。并讨论了何时选择包含或私有继承,以及私有继承提供的额外优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                       

文章《浅析C++中的is-a和has-a关系(公有继承、包含、私有继承)》讲诉了is-a与has-a的区别,并提到了实现has-a关系的两种方法:包含和私有继承。

文章《再谈C++中的is-a关系(确定你的public继承塑模出is-a关系)》讲诉了如何使用公有继承来实现is-a关系。

今天就再谈谈通过复合、私有继承来实现has-a关系。

由于翻译差异,我们姑且认为“包含”和“复合”是一个概念!

一、 使用包含实现has-a关系

这种关系的实现无非就是一个类是另外一个类的成员而已。

valarray类有头文件valarray支持,用于处理数值。
下面我们实现自己的Student类,包含valarray类的成员。

class Student{private:    string name;    valarray<double> scores;    ...};
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

上诉代码显示:Student类的成员函数可以使用string和valarray类的公有接口来访问和修改name和scores对象。但是在类的外面不允许这样做,只能通过Student类的公有接口访问name和scores.
这就是我们所说的Student获得了其成员对象的实现而没有获得接口。
因此,可以如下使用被包含对象的接口:

double Student::Average() const{    if(scores.size() > 0)        return scores.sum()/scores.size();    else        return 0;}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

二、使用私有继承实现has-a关系

c++还有另一种实现has-a关系的途径—-私有继承。使用私有继承,基类的公有成员和保护成员都将成为派生类的私有成员。这意味着基类方法将不会成为派生对象公有接口的一部分,但可以在派生类的成员函数中使用它们。
使用公有继承,基类的公有方法将成为派生类的公有方法。简而言之,派生类将继承基类的接口,这是is-a关系的一部分。使用私有继承,基类的公有方法将成为派生类的私有方法。简而言之,派生类不能继承基类的接口。正如从被包含对象中看到的,这种不完全继承是has-a关系的一部分。
因此私有继承提供的特性与包含相同:获得实现,但不获得接口。所以,私有继承也可以用来实现has-a关系。代码如下:

class Student : private std::string, private std::valarray<double>{public:    ...};
  
  • 1
  • 2
  • 3
  • 4
  • 5

与使用包含的第一个区别:
包含版本提供了两个被显示命名的对象成员,而私有继承提供了两个无名称的子对象成员。

与使用包含的第二个区别:
私有继承是使用类名而不是成员名来标识构造函数。
包含的构造函数:

Student(const char* str, const double *pd, int n):name(str),scores(pd,n){}
  
  • 1
  • 2
  • 3
  • 4

私有继承的构造函数:

Student(const char* str, const double *pd, int n):std::string(str),std::valvarray<double>(pd, n){}
  
  • 1
  • 2
  • 3
  • 4

三、使用包含还是私有继承

由于既可以使用包含,也可以使用私有继承来建立has-a关系。大多数c++程序员倾向于前者。

不过私有继承所提供的特性确实比包含多。例如,假设类包含保护成员,则这样的成员在派生类中是可用的,但在继承层次机构外是不可用的。

如果使用组合奖这样的类保护在另一类中,则后者将不是排成类,而是位于继承层次结构之外,因此不能访问保护成员。但通过继承的到的将是派生类,因此他能够访问保护成员。

另一种需要使用私有继承的情况是需要重新定义虚函数。派生类可以重新定义虚函数,但包含类不能。使用私有继承,重新定义的函数将只能在类中使用,而不是公有的。

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值