您的位置:首页 > 编程语言 > C语言/C++

《Effective C++》第六章:继承与面向对象设计

2017-06-27 17:56 330 查看
条款32:确定你的public继承塑模出is-a关系

is-a的关系就是说派生类一定是一个基类,额,通俗一点说就是派生类可以当做基类一样来使用。即本章阐述的观点就是,public继承就意味着is-a。适用于base classes身上的每一件事一定也适用于derived classes身上,确保base能做的事,derived也一定可以做

条款33:避免遮掩继承而来的名称

考虑下面这个例子:

class Base
{
private:
int x;
public:
virtual void mf1() = 0;
virtual void mf1(int);
virtual void mf2();
void mf3();
void mf3(double);
};

class Derived:public Base
{
public:
virtual void mf1();
void mf3();
void mf4()
};
Derived d;
int x;
d.mf1();
d.mf1(x);    //报错
d.mf2();
d.mf3();
d.mf3(x);    //报错
由此可见,派生类会遮掩基类的名称,无论重载。我们可以使用using来使得名字可见。

条款34:区分接口继承和实现继承

身为class设计者,有时候你会希望只继承成员函数的接口(纯虚函数);有时候你又会希望derived class同时继承函数的接口和实现,但又希望能够覆写实现(虚函数);又有时候你希望derived class同时继承函数的接口和实现,但不允许覆写任何东西(普通函数)。

条款35:考虑virtual函数以外的其他选择

1、借由Non-Virtual Interface手法实现Template Mehod模式

即将virtual函数声明为private,由public非虚函数调用这个虚函数..就是在virtual实现了一层封装,可以在虚函数调用前后做一些操作

2、由函数指针实现回调

3、所谓的Strategy模式,个人理解为复合,将基类A当做一个类B的成员变量,这样的话,每个A的派生类都适用于B(而且A的派生类可能重写A中的虚函数),比如下面例子:

class GameCharacter;
class HealthCalcFucn
{
public:
virtual int calc(const GameCharacter& gc) const;
};

class GameCharacter
{
public:
explicit GameCharacter(HealthCalcFucn *phcf);
int healthValue()
{
pHealthCalc(*this);
}
private:
HealthCalcFucn *pHealthCalc;
}
这样每个HealthCalcFunc的派生类都适用于GameCharacter这个类。

条款36:绝不重新定义继承而来的non-virtual函数

假设我们定义以下关系:

class B
{
public:
void mf();
};
class D:public B{ ... };

//对于以下调用
D x;
B* pb = &x;
pb->mf();

D* pd = &x;
pd->mf();
两者调用的是同一个mf()函数么?其实有可能不是一个。虽然pb和pd都指向了同一个对象。如果D也定义了自己的一份mf()那么就会发生上述情况。因为对于non-virtual的调用都是静态绑定。而虚函数却是动态绑定的。一旦重新定义了继承而来的非虚函数,那么每一个D都是一个B就不为真,违反了is-a的设计原则,并且如果D真的有必要实现与B不同的mf(),那么应该将mf()声明为virtual。

条款37:绝不重新定义继承而来的缺省参数值

由于上一条款绝不重新定义继承而来的non-virtual函数,所以本章讨论将局限于继承一个带有缺省参数值的virtual函数。那么本条款成立的理由十分明确:virtual是动态绑定,而缺省参数却是静态绑定。所以即使派生类重新定义了缺省参数值,参数值也不会表现为多态。解决方法是条款35提出的NVI(non-virtual-interface)手法,将缺省参数放在public非虚函数上,而将虚函数声明为private。

条款38:通过复合塑模出has-a或根据某物实现出

当复合发生于应用域的对象之间,表现出has-a的关系;当它发生于实现域内则是表现出根据某物实现出的关系。......抽象

条款39:明智而审慎的使用private继承

探讨的是private继承,public继承是is-a关系,而private继承纯粹是一种实现技术,意味着只有实现被继承,而接口被略去,即上一条款所说的根据某物实现出的概念。那么什么时候用复合,什么时候用private继承呢?首先我们从类的大小来分析。一个空类或者不含数据成员的类大小通常为1个字节,当使用复合的时候,这个类成员会占用4个字节,因为边界对齐。如果使用private继承,这个类是不占用空间的。另外如果想使用一个类的protected成员,那么必须是private继承了。

over...这一章节算是更完了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Effective C++ C++ 编程