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也可以成为重载的条件

重定义:

发生继承

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

重写:

父类中有虚函数

发生了继承

子类重写了虚函数

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

相关推荐
XiaoLeisj44 分钟前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
励志成为嵌入式工程师2 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉2 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer2 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq2 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
记录成长java4 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
前端青山4 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
青花瓷4 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
睡觉谁叫~~~4 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
音徽编程4 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust