一、代码重用
在C语言中重用代码的最主要方式就是封装成函数然后其他地方调用这个函数,但是一个函数往往通用性不是很大。所以C语言中很多代码复用都是修改粘贴代码。C++很重要的一个特征就是代码重用,C++可以用继承或组合或者模板的方式来重用。通过组合或继承现有的的类来创建新类,而不是重新创建它们。我们创建了一个基类,用我们的类去继承基类,我们的类就有了基类的功能。
二、继承
继承是使用已经编写好的类来创建新类,新的类具有原有类的所有属性和操作,也可以在原有类的基础上作一些修改和增补。
新类称为派生类或子类,原有类称为基类或父类,派生类是基类的具体化。下图是一个形象的例子:
从图中我们可以看出,机动车是车的一种,而汽车和货车又是机动车的一种。机动车具有继承自车的一切功能。
三、公有、私有、保护继承
继承方式有公有,私有,保护继承三种方式。Private成员无论用何种方式继承在派生类中都不可直接访问。除了Private成员外,公有继承访问方式不变,私有继承所有成员变为Private,保护继承public成员编程protected成员。下面是一个继承方式的示例:
#include <iostream>
using namespace std;
class Base
{
public:
int x_;
protected:
int y_;
private:
int z_;
};
class PublicInherit : public Base
{
public:
void Test()
{
x_ = 10;
y_ = 20;
}
private:
int a_;
};
class PublicPublicInherit : public PublicInherit
{
public:
void Test()
{
y_ = 20;
}
};
class PrivateInherit : private Base
{
public:
void Test()
{
x_ = 10;
y_ = 20;
//z_ = 30;
}
};
int main(void)
{
PublicInherit pub;
pub.x_ = 20;
PrivateInherit pri;
//pri.x_ = 10;
return 0;
}
四、默认继承保护级别
对于struct来说,默认继承方式是公有继承,默认成员是公有成员。对于class来说,默认成员是私有成员默认继承是私有继承。
五、接口继承与实现继承
我们将类的公有成员函数称为接口。
公有继承,基类的公有成员函数在派生类中仍然是公有的,换句话说是基类的接口成为了派生类的接口,因而将它称为接口继承。
实现继承,对于私有、保护继承,派生类不继承基类的接口。派生类将不再支持基类的公有接口,它希望能重用基类的实现而已,因而将它称为实现继承。
六、继承与重定义
看下面一个例子:
#include <iostream>
using namespace std;
class Base
{
public:
Base() : x_(0) {}
int GetBaseX() const { return x_; }
void Show()
{
cout<<"Base::Show ..."<<endl;
}
int x_;
};
class Derived : public Base
{
public:
Derived() : x_(0) {}
int GetDerivedX() const { return x_; }
void Show(int n)//重载
{
cout<<"Derived::Show "<<n<<endl;
}
void Show()
{
cout<<"Derived::Show ..."<<endl;
}
//对基类成员的重定义
int x_;
};
class Test
{
public:
Base b_;
int x_;
};
int main(void)
{
Derived d;
d.x_ = 10;
d.Base::x_ = 20;
cout<<d.GetBaseX()<<endl;
cout<<d.GetDerivedX()<<endl;
d.Show();
d.Base::Show();
d.Show(4);
cout<<sizeof(Derived)<<endl;
cout<<sizeof(Test)<<endl;
return 0;
}
运行结果:
20
10
Derived::Show ...
Base::Show ...
Derived::Show 4
8
8
10
Derived::Show ...
Base::Show ...
Derived::Show 4
8
8
从例子可以看出,如果派生类定义了和基类相同的成员变量或成员函数,那么派生类的成员变量和成员函数会覆盖基类的成员,这就是重定义。
七、继承与组合
无论是继承与组合本质上都是把子对象放在新类型中,两者都是使用构造函数的初始化列表去构造这些子对象。
组合是在希望新类内部具有已存在的类的功能时使用,而不是希望已存在类作为它的接口。组合通过嵌入一个对象以实现新类的功能,而新类用户看到的是新定义的接口,而不是来自老类的接口(has-a)。
如果希望新类与已存在的类有相同的接口(在这基础上可以增加自己的成员)。这时候需要用继承,也称为子类型化。(is-a)