C++远征_继承篇

继承篇

继承:

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
{

};
发布了51 篇原创文章 · 获赞 27 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_39446719/article/details/89719865