c++多态

目录

多态的概念

多态实现计算器案例

c++如何实现动态绑定

纯虚函数和抽象类

纯虚函数和多继承

虚析构函数

虚析构函数作用

纯虚析构函数

[重载 重定义 重写](#重载 重定义 重写)


多态的概念

多态:一种接口,多种形态

静态多态:如果函数的调用,在编译阶段就可以确定函数的调用地址,并产生代码,就是静态多态(编译时多态)

动态多态:调用地址不能编译不能在编译期间确定,而需要在运行时才能决定,这这就属于晚绑定(动态多态,运行时多态)

发生多态的四个条件:

父类中有虚函数

必须发生继承

子类必须重写虚函数(函数名 参数 返回值一致 函数的内容可以不一致)

父类的指针或引用指向子类的对象

cpp 复制代码
#include <iostream>

using namespace std;

class Animal
{
    public:
		virtual void speak()
		{
			cout << "动物在说话" << endl;
		}
};
class Dog:virtual public Animal
{
    public:
		//重写虚函数 函数的返回值 参数 函数名一样
		void speak()
		{
			cout << "狗在说话" << endl;
		}
};
class Cat:virtual public Animal
{
    public:
		//重写虚函数 函数的返回值 参数 函数名一样
		void speak()
		{
			cout << "猫在说话" << endl;
		}
};
//如果两个类发生了继承 父类和子类编译器都会自动转换 不需要人为转换
void do_work(Animal &obj)//多态接口 一个函数实现不同功能
{
	obj.speak();//地址早绑定->加上函数前面加上virtual 地址晚绑定
}

void test01()
{
	Animal p1;
	do_work(p1);//动物

	Dog p2;
	do_work(p2);//狗
	
	Cat p3;
	do_work(p3);//猫
}

int main()
{
    test01();
    return 0;
}

多态实现计算器案例

cpp 复制代码
#include <iostream>
using namespace std;

class Calc
{
    public:
		virtual int mycalc(int a,int b)
		{
			return 0;		
		}
};
		
class Add:public Calc
{
    public:
		int mycalc(int a,int b)
		{
			return a + b;		
		}

};
class Mul:public Calc
{
    public:
		int mycalc(int a,int b)
		{
			return a * b;		
		}

};
class Sub:public Calc
{
    public:
		int mycalc(int a,int b)
		{
			return a - b;		
		}

};
		
int do_calc(int a,int b,Calc &obj)
{
	return obj.mycalc(a,b);
}

void test01()
{
	Add p1;
	cout << do_calc(3,4,p1) << endl;
	
	Mul p2;
	cout << do_calc(3,4,p2) << endl;

	Sub p3;
	cout << do_calc(3,4,p3) << endl;

}

int main()
{
    test01();
    return 0;
}

c++如何实现动态绑定

为什么可以根据传入对象的不同来执行不同的语句?

纯虚函数和抽象类

纯虚函数:将虚函数等于0 实质是将虚函数 表的函数入口设为NULL

抽象类:一个类如果有纯虚函数,那么这个类就是一个抽象类,抽象类不能实例化对象

继承抽象类的子类也是一个抽象类,如果子类重写了虚函数,那么子类就不是抽象类

cpp 复制代码
class Calc
{
    public:
        virtual int mycalc(int a,int b) = 0;//虚函数等于0 纯虚函数
};

class Mob:public Calc
{
    public:
          //子类继承了抽象类 子类也是抽象类
           //如果子类重写虚函数 就不是抽象类
};

//如果有纯虚函数的类 叫做抽象类 抽象类无法实例化对象
void test()
{
    //Cacl p;//错误 
    Mod p1;
}

纯虚函数和多继承

多继承带来了一些争议,但是接口继承可以说一种毫无争议的运用了。
绝大数面向对象语言都不支持多继承,但是绝大数面向对象对象语言都支持接口的概念, c++ 中没有接口的概念, 但是可以通过纯虚函数实现接口。
接口类中只有函数原型定义,没有任何数据定义。
多重继承接口不会带来二义性和复杂性问题。接口类只是一个功能声明,并不是功能实现,子类需要根据功能说 明定义功能实现。
注意 : 除了析构函数外,其他声明都是纯虚函数。

虚析构函数

虚析构函数作用

在调用基类的析构函数之前,先调用子类的析构函数

cpp 复制代码
#include <iostream>

using namespace std;

class Animal
{
    public:
		virtual void speak()
		{
			cout << "动物在说话" << endl;
		}
		virtual ~Animal()
		{
			cout << "动物的析构" << endl;
		}
};
class Dog:virtual public Animal
{
    public:
		//重写虚函数 函数的返回值 参数 函数名一样
		void speak()
		{
			cout << "狗在说话" << endl;
		}
		~Dog()
		{
			cout << "狗的析构" << endl;
		} 
};
class Cat:virtual public Animal
{
    public:
		//重写虚函数 函数的返回值 参数 函数名一样
		void speak()
		{
			cout << "猫在说话" << endl;
		}
};
//如果两个类发生了继承 父类和子类编译器都会自动转换 不需要人为转换
void do_work(Animal &obj)//多态接口 一个函数实现不同功能
{
	obj.speak();//地址早绑定->加上函数前面加上virtual 地址晚绑定
}

void test01()
{
	Animal *p = new Dog;
	p->speak();//调用狗的speak
	delete p;//加virtual 调用动物的析构 加virtual之后先调用狗的析构 再调用动物的析构
}

int main()
{
    test01();
    return 0;
}

纯虚析构函数

虚构函数等于零

class Animal

{

public:

virtual void speak()

{

cout << "动物在说话" << endl;

}

virtual ~Animal() = 0;//

};

重载 重定义 重写

重载:

函数名相同

同一个作用域

参数的个数、顺序、类型不一致

const也可以成为重载的条件

重定义:

发生继承

子类和父类有同名的变量和函数,父类中同名的变量和函数会被隐藏

重写:

父类中有虚函数

发生了继承

子类重写了虚函数

函数名、返回值、参数一致,函数体不一致

相关推荐
傻啦嘿哟8 分钟前
如何使用 Python 开发一个简单的文本数据转换为 Excel 工具
开发语言·python·excel
大数据编程之光12 分钟前
Flink Standalone集群模式安装部署全攻略
java·大数据·开发语言·面试·flink
初九之潜龙勿用13 分钟前
C#校验画布签名图片是否为空白
开发语言·ui·c#·.net
爱摸鱼的孔乙己28 分钟前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
Dola_Pan30 分钟前
C语言:数组转换指针的时机
c语言·开发语言·算法
ExiFengs30 分钟前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
paj12345678931 分钟前
JDK1.8新增特性
java·开发语言
IT古董39 分钟前
【人工智能】Python在机器学习与人工智能中的应用
开发语言·人工智能·python·机器学习
繁依Fanyi42 分钟前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse
烦躁的大鼻嘎1 小时前
模拟算法实例讲解:从理论到实践的编程之旅
数据结构·c++·算法·leetcode