栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++继承 和 多态

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++继承 和 多态

继承的好处,可以减少代码的重复
class A : 继承方式 B;
A类为子类,B类为父类
子类的成员分别由从父类继承来的成员 和自己本身的成员构成。

继承方式有public,protect,private 三种
首先 不管是哪种继承方式,子类都无法继承父类的私有成员,并非没有继承,而是私有成员被隐藏。
如果是公有继承,则子类直接继承父类中除了私有的成员,并且不做任何变化
如果是保护继承,父类中除了私有的成员在子类中全部变成保护权限(保护权限 类外不可以访问)
如果是私有继承,则全部变成私有权限

继承中的对象模型
cl /d1 reportSingleClassLayout类名 文件名.cpp 可以在命令行中查看类的结构

子类继承父类后,当创建子类对象,也会调用父类的构造函数
继承中的构造和析构的顺序如下,先构成父类再构成子类,析构顺序反过来

继承同名成员处理方式
如果通过子类对象访问父类的同名成员,需要加入作用域 s.father::age

多继承语法
允许一个类继承多个类
语法: class 子类: 继承方式 父类1, 继承方式 父类2,。。。
多继承可能引发父类中有同名成员的出现, 因此要室友作用域加以区分

菱形继承
两个子类同时继承一个父类,又有某个子类同时继承两个子类,这种继承被称为菱形继承
比如 动物 - 羊,驼-羊驼, 因为羊驼继承了羊和驼,那么数据会产生二义性
利用虚继承解决菱形继承问题, 在继承类型前加上关键字virtual 变成虚继承

多态

多态分为静态多态和动态多态
静态多态:函数重载和运算符重载都是静态多态,复用函数名
动态多态: 子函数和虚函数实现运行时多态
区别:
静态多态的函数地址早绑定,即编译阶段确定函数地址
动态多态的函数地址晚绑定,运行阶段才确定函数地址

class Animal {
public:
	virtual void speak() {
		cout << "animal speak chinese" << endl;
	}
};

class Cat : public Animal {
public:
	void speak() {
		cout << "cat speak meow" << endl;
	}
};

void doSpeak(Animal* animal) {  // 在c++中,父类的指针可以直接指向子类
	animal->speak();  
}


int main() {
	Cat c;
	c.speak();
	doSpeak(&c);  //执行的是动物在说话,因为地址早绑定了 如果想要地址晚绑定 在说话函数前加上virtual
}

动态多态满足条件
1.有继承关系
2.子类要重写父类的虚函数

多态原理

类中含有virtual 成员函数,即便不再含有其他变量和函数,该类仍然占有4字节(空类只占1字节),原因是virtual 成员函数会给类添加一个virtual function ptr, 该指针指向一个列表,里面记录着虚函数的地址,当子类继承时,也会继承该指针,并指向子类的虚函数的地址,而子类的虚函数和父类的不一样,因此,当出现Animal & animal = cat 时,此时虚函数列表为cat的列表,故而animal.speak访问的是cat的speak。

在多态中,通常父类中虚函数的实现是毫无意义的,主要调用子类重写的内容,因此可以将虚函数改成纯虚函数

纯虚函数写法:
virtual 返回值类型 函数名(参数列表) = 0;
当类中有了虚函数,这个类也称为抽象类
抽象类的特点:无法实例化对象,且子类必须重写抽象类的纯虚函数,否则子类也是抽象类

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在析构时无法调用到子类的析构代码
解决方式:将父类的析构函数改成虚析构和纯虚析构
虚析构和纯虚析构的共性:可以解决父类指针释放子类对象,都需要具体的函数实现
区别: 如果是纯虚析构,那么该类属于抽象类,无法实例化对象。

虚析构和纯虚析构都需要声明 和代码实现, 但如果子类中没有堆区数据,可以不写虚析构或者纯虚析构
示例代码:

#include "base.h"

class Animal {
public:
	Animal() {
		cout << "Animal 构造函数" << endl;
	}
	virtual ~Animal() = 0;
	virtual void speak() = 0;
};
Animal :: ~Animal() {
	cout << "Animal 析构" << endl;


}
class Cat:public Animal {
public:
	string* name;
	Cat(string nom) {
		cout << "Cat 构造函数" << endl;
		name = new string(nom);
	}
	void speak() {
		cout << *this->name << " is speaking" << endl;
	}

	~Cat() {
		cout << "Cat 析构函数" << endl;
		if (this->name != NULL) {
			delete  name;
			name = NULL;
		}
	}

};

int main() {
	Animal* animal = new Cat("tom");
	animal->speak();
	delete animal;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1022488.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号