继承篇
继承:
class Worker: public Person
{
public:
void work();
int m_iSalary;
};
// Person -> 基类/父类
// Worker -> 派生类/子类
内存中的对象
实例化的过程
Worker *p = new Worker();
delete p;
p = NULL;
实例化时会先调用 Person()
再调用 Worker()
;销毁时会先调用 ~Worker()
再调用 ~Person()
。
即 先调用 父类的构造函数, 再调用子类的构造函数;先调用子类的析构函数,再调用父类的析构函数。
继承方式
公有继承 :public
继承的时候将会把父类的 public 继承,父类的 protected 继承。
public 属性可以在任意地方调用,而 protected 属性只能在成员函数中调用
对于父类的 private 属性,子类无法继承和访问
公有继承总结:
保护继承 :protected
私有继承 :private
保护继承和私有继承均修改了父类的访问限定符
私有继承类似于 Has a 的关系
覆盖和隐藏(重载和重写)
隐藏(重写)
父子关系 成员同名 隐藏
class Person
{
public:
void play(); // 成员函数同名
protected:
string m_strName;
string code; // 数据成员同名
};
class Soldier:public Person
{
public:
void play();
void work();
protected:
int m_iCode;
int code;
};
int main(void) {
Soldier soldier;
soldier.play();
soldier.Person::play();
return 0;
}
void Solider::work()
{
code = 1234;
Person::code = "5678";
}
覆盖(重载)
isa
class Person {
public:
Person(string m_strName = "Jim");
virtual ~Person(); // 虚 析构函数
void eat();
void play();
public:
string m_strName;
};
class Soldier:public Person {
public:
Soldier(string m_strName = "Marry",int m_iAge = 10);
virtual ~Soldier(); // 虚 析构函数
void play(int x);
void work();
public:
int m_iAge;
};
父类的声明,子类的定义
Person *p = new Solider;
void func(Person &p) {
cout << p.m_strName;
cout << "我是人类" << endl;
}
// 调用时,可以传入 Person 或者 Person 的子类
func(new Solider());
delete p;
p = NULL;
// 打印结果:
// Marry
// 我是人类
注意:
若不加 虚析构函数 ,则释放内存时只会执行Person
的析构函数,不会执行子类Soldier
的析构函数;父类加上 虚 virtual
修饰符后,子类的析构函数在父类调用之后也会自动调用。
// 会创建临时对象 p,随后被销毁
void test1(Person p)
{
p.play();
}
// 以下两个函数并不会产生新的临时对象,效率更高
void test2(Person &p)
{
p.play();
}
void test3(Person *p)
{
p->play();
}
test1(p);
test1(s);
test2(p);
test2(s);
test2(&p);
test2(&s);
多继承和多重继承
多重继承
即 步兵类 继承 士兵类,士兵类 继承 人类。存在隔代 爷孙关系。
多继承
class Worker
{
};
class Farmer
{
};
class MigrantWorker: public Worker, public Farmer //若不写则为private
{
};
注意:
在实例化 MigrantWorker
的时候,会根据初始化列表的顺序 分别调用父类的构造函数
析构函数顺序正好相反
菱形继承
如此,同时存在了多继承和多重继承,当实例化 D 对象的时候,会同时调用两次A 的构造函数,浪费资源。并且在内存中会分别维护两份 Person 数据
使用虚继承可以解决当前问题。
虚继承
关键字: virtual
class Worker: virtual public Person // 虚基类
{
};
class Farmer: virtual public Person
{
};
class MigrantWorker:public Worker,public Farmer
{
};