内容参考于《21天学通C++》(第八版)
不去纠结C++的原理和细节,从C的角度去学习C++,再通过C++项目去加深理解
五.继承
1. 示例
#include <iostream>
using namespace std;
class Fish
{
public:
bool isFreshWaterFish;
void Swim()
{
if (isFreshWaterFish)
cout << "Swims in lake" << endl;
else
cout << "Swims in sea" << endl;
}
};
class Tuna : public Fish
{
public:
Tuna()
{
isFreshWaterFish = false;
}
};
class Carp : public Fish
{
public:
Carp()
{
isFreshWaterFish = true;
}
};
int main()
{
Carp myLunch;
Tuna myDinner;
cout << "About my food:" << endl;
cout << "Lunch: ";
myLunch.Swim();
cout << "Dinner: ";
myDinner.Swim();
return 0;
}
2. 访问限定符 protected
Fish 类包含公有属性 isFreshWaterFish。派生类 Tuna 和 Carp 通过设置它来定制 Fish 的行为—在海水还是淡水中游动。然而,程序存在一个严重的缺陷:如果您愿意,可在 main( )中修改这个被声明为公有的标志,这为在 Fish 类外部操纵该标志打开了方便之门:
myDinner.isFreshWaterFish = true; // but Tuna isn't a fresh water fish!
显然,需要让基类的某些属性能在派生类中访问,但不能在继承层次结构外部访问。这意味着您希望 Fish 类的布尔标志 isFreshWaterFish 可在派生类 Tuna 和 Carp 中访问, 但不能在实例化 Tuna 和 Carp的 main( )中访问。为此,可使用关键字 protected。
class Fish
{
protected:
bool isFreshWaterFish;
public:
void Swim()
{
if (isFreshWaterFish)
cout << "Swims in lake" << endl;
else
cout << "Swims in sea" << endl;
}
};
3. 派生类对基类传参数
class Base
{
public:
Base(int someNumber) // overloaded constructor
{
// Use someNumber
}
};
Class Derived: public Base
{
public:
Derived(): Base(25) // instantiate Base with argument 25
{
// derived class constructor code
}
};
4. 调用基类中被覆盖的方法
比如派生覆盖了基类的Swin(),那么派生又想调用基类的Swin()
myDinner.Fish::Swim();
从字面意思,基类是派生的一个成员。
5. 构造顺序
基类对象在派生类对象之前被实例化。因此,首先构造 Tuna 对象的Fish 部分,这样实例化 Tuna 部分时,成员属性(具体地说是 Fish 的保护和公有属性)已准备就绪,可以使用了。实例化 Fish 部分和 Tuna 部分时,先实例化成员属性(如 Fish::isFreshWaterFish),再调用构造函数,确保成员属性准备就绪,可供构造函数使用。这也适用于 Tuna::Tuna( )。
6. 析构顺序
析构顺序与构造顺序相反。
7. 私有继承 private
class Base
{
// ... base class members and methods
};
class Derived: private Base // private inheritance
{
// ... derived class members and methods
};
私有继承意味着在派生类的实例中, 基类的所有公有成员和方法都是私有的—不能从外部访问。
换句话说,即便是 Base 类的公有成员和方法,也只能被 Derived 类里使用,而无法通过 Derived 实例来使用它们。
#include <iostream>
using namespace std;
class Motor
{
public:
void SwitchIgnition()
{
cout << "Ignition ON" << endl;
}
void PumpFuel()
{
cout << "Fuel in cylinders" << endl;
}
void FireCylinders()
{
cout << "Vroooom" << endl;
}
};
class Car :private Motor // private inheritance
{
public:
void Move()
{
SwitchIgnition();
PumpFuel();
FireCylinders();
}
};
int main()
{
Car myDreamCar;
myDreamCar.Move();
return 0;
}
如果有一个 RaceCar 类,它继承了 Car 类,则不管 RaceCar 和 Car 之间的继承关系是什么样的, RaceCar 都不能访问基类 Motor 的公有成员和方法。这是因为 Car 和 Motor 之间是私有继承关系,这意味着除 Car 外,其他所有实体都不能访问基类 Motor 的公有或保护成员。换句话说,编译器在确定派生类能否访问基类的公有或保护成员时,考虑的是继承层次结构中最严格的访问限定符。
8. 多继承
class Platypus: public Mammal, public Reptile, public Bird
{
// ... platypus members
};
9. 使用 final 禁止继承
说明本类是最终结果。