JBe*_*ley 10 c++ oop traits composition aggregation
假设我们有两个类,A
并且B
.当使用组合来建模"has-a"或"is-implemented-in-terms-of"关系(例如B
has-a A
)时,缺点与继承之一是B
不包含A
它需要的公共功能.为了获得对A
公共函数的访问,有必要提供转发函数(与继承相反,B
继承所有A
的公共函数).
为了给出一个更具体的例子,假设我们有一个Person
它具有-A ContactInfo
:
using namespace std;
class ContactInfo
{
public:
ContactInfo();
void updateAddress(string address);
void updatePhone(string phone);
void updateEmail(string email);
private:
string address;
string phone;
string email;
};
class Person
{
public:
Person();
// Forwarding functions:
void updateAddress(string address){contactInfo.updateAddress(address)};
void updatePhone(string phone){contactInfo.updatePhone(phone)};
void updateEmail(string email){contactInfo.updateEmail(email)};
private:
ContactInfo contactInfo;
};
Run Code Online (Sandbox Code Playgroud)
在设计中忽略任何不足之处(这只是一个人为的例子来证明我下面的问题),我不得不不厌其烦地从复制确切函数签名ContactInfo
中Person
.在一个更复杂的例子中,可能有许多这样的函数,以及许多组合类的层,导致许多代码重复,具有所有常见的维护和容易出错的问题等.
尽管如此,根据Meyers的Effective C++的第38项和Sutter的Exceptional C++的第24项(链接)等来源,建议使用"has-a"或"is-implemented-in-terms "来建模.
在研究这个问题的同时,我偶然发现了维基百科这篇讨论相同主题的文章.在文章的底部,它建议如下:
使用组合代替继承的一个缺点是组合类提供的所有方法必须在派生类中实现,即使它们只是转发方法.[...]使用特征可以避免这种缺点.
我对特质的概念和我读过的所有内容都相当新,我发现很难与上述陈述联系起来.因此我的问题是:如何使用特征来避免使用合成转发函数?基于我的例子(Person
和ContactInfo
)的答案是理想的.
编辑:只是为了澄清,为了回应一些答案,我知道私有继承作为建模"is-implemented-in-terms-of"的组合的替代.我的问题与此无关,它具体涉及维基百科关于特征的陈述的含义.我不是要求组成的替代品.我加粗了我的问题,让我更清楚这就是我所要求的.
小智 1
首先,我应该提到,C++/STL 和 PHP、Lasso 等语言中的特征是不同的东西。看起来维基百科的文章提到了类似 PHP 的特征,因为 C++/STL 特征不是为多态重用而设计的(我们是谈论具有多态行为的代码重用,对吧?)。他们旨在简化模板类的声明。
Traits 用于某些不支持多重继承的语言(PHP、Lasso 等)。特征允许“模拟”多重继承(但多重继承和特征并不完全相同)。
相比之下,C++ 不支持 PHP 特性,但支持多重继承。因此,如果谈论 C++,那么类似特征的解决方案将是这样的:
class VisibleTrait
{
public:
virtual void draw();
};
class SolidTrait
{
public:
virtual void collide(Object objects[]);
};
class MovableTrait
{
public:
virtual void update();
};
// A player is visible, movable, and solid
class Player : public VisibleTrait, MovableTrait, SolidTrait
{
};
// Smoke is visible and movable but not solid
class Smoke : public VisibleTrait, MovableTrait
{
};
// A hause is visible and solid but not movable
class House : public VisibleTrait, SolidTrait
{
};
Run Code Online (Sandbox Code Playgroud)
所以回答你的问题
如何使用特征来避免转发带有组合的函数?
1)特征不会避免使用组合来转发函数,因为特征独立于组合而工作。(来自 Wikipadia 的文章关于特征和组合之间的关系有点误导)
2)类似 PHP/Lasso 的特征可以在 C++ 中通过多重继承进行部分模拟。