IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C++入门教程】学习笔记4——继承和多态 -> 正文阅读

[C++知识库]【C++入门教程】学习笔记4——继承和多态

继承

基本语句

class 子类(派生类): 继承方式 父类(基类)

class A:public Base{

};
继承方式

公共继承:无变化
保护继承:父类的公共也变成了自己的保护
私有继承:父类中的所有权限的成员都变成了自己的私private

继承中的对象模型

从父类所有的非静态成员,不管权限,都属于类的对象

继承中构造和析构顺序

构造顺序:父类 - 子类
析构顺序: 子类 - 父类

继承中同名成员处理方式

访问子类:直接访问
访问父类:加作用域
如果子类中有同名函数,那么会覆盖父类所有的函数,包括重载的,所以都要加作用域

class Base{
public:
	int a=100;
	void func(){
		cout<<"Base func"<<endl;
	}
	void func(int a){
		cout<<"Base func"<<endl;
	}
};
class Son: public Base{
public:
	int a=100;
	void func(){
		cout<<"Son func"<<endl;
	}
};
int main(){
	Son A;
	Base B;
	cout<<A.a<<" "<<A.Base::a<<endl;
	A.Base::func();
	A.Base::func(10);//A.func(10)是错的
}
继承同名静态成员处理方式

和非静态成员处理方式一样,但是既可以通过对象访问,也可以通过类名访问

class Base{
public:
	static int a;
	static void func(){
		cout<<"Base func"<<endl;
	}
};
int Base::a=100;//类内声明,类外初始化
class Son: public Base{
public:
	static int a;
	static void func(){
		cout<<"Son func"<<endl;
	}
};
int Son::a=200;

int main(){
	Son A;
	//通过对象访问
	cout<<A.a<<" "<<A.Base::a<<endl;
	A.func();
	A.Base::func();
	//通过类名访问
	cout<<Son::a<<" "<<Son::Base::a<<endl;
	Son::func();
	Son::Base::func();

}
多继承语法

一个类可以继承多个类
同名成员加作用域区分

class Base1{
public:
	int a=100;
};
class Base2{
public:
	int a=200;
};
class Son:public Base1,public Base2{
public:
	int a=300;
};

int main(){
	Son s;
	cout<<s.a<<" "<<s.Base1::a<<" "<<s.Base2::a<<endl;

}
菱形继承问题

两个子类继承同一个父类,又有某个子类继承这两个子类,也就是最下的子类继承了两个父类,所以有二义性,用虚继承解决这个问题

class Base{
public:
	int a;
};
//利用虚继承解决二义性
//继承之前加关键词 virtual
//Base被称为虚基
class Son1:virtual public Base{};
class Son2:virtual public Base{};
class Grandson:public Son1,public Son2 {};
int main(){
	Grandson gs;
	gs.Son1::a=10;
	gs.Son2::a=20;
	cout<<gs.Son1::a<<" "<<gs.Son2::a<<endl;
	//发生虚继承后,相当于共享Base数据
	//当加了virtual后,son1和son2继承的是虚基类指针 vbptr指向虚基类表vbtable,所以数据只有一份
}

多态

多态的基本概念

静态多态:函数重载和运算符重载
动态多态:派生类和虚函数实现运行时多态
静态多态的函数地址早绑定,编译阶段确定地址
动态多态的函数地址晚绑定,运行阶段确定地址

动态多态
class Animal{
public:
	virtual void speak(){
		cout<<"Animal speak"<<endl;
	}
};
class Cat : public Animal{
public:
	void speak(){
		cout<<"cat speak"<<endl;
	}
};
//函数的地址早绑定了(doSpeak的参数Animal早就和class Animal绑定了)
//传cat,可以编译,但是输出的是animal类的spe
//利用虚函数解决,加入virtual void speak()后输出的就是cat speak
void doSpeak(Animal &m){
	m.speak();
}
int main(){
	Cat cat;
	doSpeak(cat);
}
// 动态多态使用
//1. 有继承
//2. 子类重写(注意不是重载)父类的虚函数
//3. 父类的指针指向子类对象
多态的原理剖析
int main(){
	cout<<sizeof(Animal)<<endl;
	//Animal class 不加virtual空类的大小是1,加了是8(多了一个指针)
	//指针vfptr(虚函数指针),指向虚函数表vftable
	//vftable里,表的内部记录虚函数的地址,&Animal::speak
	cout<<sizeof(Cat)<<endl;
	//Animal class 不加virtual空类的大小是1,加了是8(多了一个指针)
	//指针vfptr(虚函数指针),指向虚函数表vftable
	//vftable里,表的内部记录虚函数的地址,&Animal::speak
	//重写后,子类的虚函数表 会替换 成子类的虚函数地址&Cat::speak
}
纯虚函数和抽象类
class Animal{
public:
	virtual void speak() = 0;
};

当类中有了纯虚函数,则类为抽象类,子类必须重写纯虚函数

虚析构和纯虚析构

虚函数析构时子类的堆区数据未释放,把父类中的析构改为虚析构即可,纯虚析构

class Animal{
public:
	virtual ~Animal() = 0;
};
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-14 20:56:33  更:2022-02-14 20:58:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:21:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码