C++多态的使用

1. 多态

多种形态或多种实现方法,C++中的多态是指一种接口(指的是父类接口),多种实现方法(指的是每个子类所实现的方法),即通过父类接口实现调用子类的多种方法

1.1 构成多态性的条件:

1)具有继承关系的两个类

2)父类指针或引用指向子类

3)多种实现方法需要声明为虚函数

1.2 静态绑定

静态绑定(Static Binding),也称为早期绑定(Early Binding)或编译时绑定(Compile-time Binding),是指在程序的编译阶段确定方法、函数或操作的调用目标。在静态绑定中,编译器能够准确地确定调用哪个函数,因为调用关系在编译时已经被决定了。

静态绑定的优势在于效率高,因为编译器在编译时就能够确定调用关系,不需要在运行时进行查找。然而,静态绑定的缺点是缺乏灵活性,因为调用的目标在编译时就已经固定,无法根据运行时的条件进行动态调整。

与之相对的是动态绑定(Dynamic Binding),它是在运行时根据对象的实际类型来确定调用的方法。动态绑定通常与虚函数(virtual function)相关联,使得在运行时能够调用到对象实际类型的方法。

静态绑定(静态联编)

是指函数或表达式的地址,在编译时就已经确定

根据对象的类型确定成员的调用地址

普通函数调用: 对于全局函数或类的静态成员函数,编译器在编译时就能够确定调用的函数。

cpp 复制代码
void myFunction() {
    // some code
}

int main() {
    myFunction(); // 静态绑定
    return 0;
}

非虚函数调用: 对于非虚函数,编译器也能够在编译时确定调用的函数。

cpp 复制代码
class Base {
public:
    void nonVirtualFunction() {
        // some code
    }
};

int main() {
    Base obj;
    obj.nonVirtualFunction(); // 静态绑定
    return 0;
}

1.3 动态绑定

动态绑定(动态联编)

是指函数或表达式的地址,在运行时才确定

例子:

多态

根据指向的地址的对象的类型来确定成员的调用地址

C++中的多态性(polymorphism)通过虚函数(virtual functions)和动态绑定(dynamic binding)来实现。多态性允许在运行时根据对象的实际类型调用相应的函数,而不是根据变量或指针的静态类型。

在C++中,要实现多态性,你需要使用虚函数。虚函数是在基类中声明并在派生类中重写的函数。在基类中,你使用virtual关键字声明这个函数

duotai2.cpp

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


//多态的动态绑定
class Shape {
public:
    // 基类中的虚函数
    //virtual void draw() = 0;

    virtual void draw(){
        cout << "父类画一个形状" << endl;
    }
};

class Circle : public Shape {
public:
    // 派生类中重写基类的虚函数
    void draw(){
        cout << "子类1画圆" << endl;
    }
};

class Square : public Shape {
public:
    // 派生类中重写基类的虚函数
    void draw(){
        cout << "子类2画方" << endl;
    }
};

int main() {

    Circle circle;
    Square square;

    // 使用基类指针指向派生类对象
    Shape* shapePtr = &circle;
    shapePtr->draw(); // 动态绑定,将调用 Circle 类的 draw 函数

    Shape* shapePtr2 = &square;
    shapePtr2->draw(); // 动态绑定,将调用 Square 类的 draw 函数

    return 0;
}

2. 虚析构函数

为什么要提出虚析构函数?解决资源(子类)得不到释放的问题

析构函数用vritual关键字来进行修饰

前提:

父类的指针或引用指向子类时

cpp 复制代码
格式:
	virtual   ~类名()
	{
	}
例如:
	virtual  ~People()//虚析构函数
	{

	}	

2.1 面试题:

如果父类的析构函数不是虚函数,会带来(引起) 什么问题?

问题演示

xvgou.cpp
cpp 复制代码
//虚析构函数
class People {
public:
	~People() { 
		cout << "父类的虚构函数" << endl;
	}
};

//class People {
//public:
//	virtual ~People() { //把父类声明为虚析构函数
//		cout << "父类的虚构函数" << endl;
//	}
//};

class Son :public People{
public:
	~Son() {
		cout << "子类的虚构函数" << endl;
	}
};


int main()
{
	//写法一,因为在堆上开辟的son,所以需要手动delete释放
	People* people = new Son;
	delete people;

	//写法二,因为在栈上开辟的son,不需要手动释放,程序会自动释放
	/*Son son;
	People* people = &son;*/

	return 0;
}


可以看到子类并未释放

带来的问题:资源(子类)得不到释放的问题

如果基类的析构函数不是虚函数,而你通过基类指针删除派生类对象,将只会调用基类的析构函数,而不是派生类的析构函数,这可能导致资源泄漏。

解决:将父类的析构函数声明为虚析构函数

xvgou.cpp
cpp 复制代码
//虚析构函数
//class People {
//public:
//	~People() { 
//		cout << "父类的虚构函数" << endl;
//	}
//};

class People {
public:
	virtual ~People() { //把父类声明为虚析构函数
		cout << "父类的虚构函数" << endl;
	}
};

class Son :public People{
public:
	~Son() {
		cout << "子类的虚构函数" << endl;
	}
};


int main()
{
	//写法一,因为在堆上开辟的son,所以需要手动delete释放
	People* people = new Son;
	delete people;

	//写法二,因为在栈上开辟的son,不需要手动释放,程序会自动释放
	/*Son son;
	People* people = &son;*/


	return 0;
}

3. 限制构造函数

限制对象的生成(创建)

将构造函数放置在protected或private修饰符下,用于限制对象的生成

3.1 举例

xvgou.cpp

cpp 复制代码
//限制构造函数(将类的构造函数放在private下,限制类的实例化)
class Person {

private:
	Person() {
		cout << "person的构造函数" << endl;
	}
};



int main()
{
	//Person person;

	return 0;
}

3.2 当限制构造函数时,通过友元构造对象可行?

可以

xvgou.cpp

cpp 复制代码
//限制构造函数(将类的构造函数放在private下,限制类的实例化)
class Person {
public:
	friend void create();//声明友元函数
private:
	Person() {
		cout << "person的构造函数" << endl;
	}
};

//设置友元函数,看看可不可以实例化对象
void create() {
	Person person;
}

int main()
{
	//Person person;

	//通过友元实例化对象
	create();

	return 0;
}
相关推荐
龙俊杰的读书笔记4 小时前
[leetcode] 面试经典 150 题——篇9:二叉树(番外:二叉树的遍历方式)
数据结构·算法·leetcode·面试
刚入门的大一新生4 小时前
C++初阶-C++的讲解1
开发语言·c++
sml259(劳改版)6 小时前
数据结构--堆
数据结构·算法·
冷冷清清中的风风火火6 小时前
linux 里的创建了一个tomcat用户 怎么禁止该用户使用crontab 功能
linux·tomcat·firefox
ALex_zry7 小时前
C++17模板编程与if constexpr深度解析
开发语言·c++·性能优化
独家回忆3647 小时前
每日算法-250409
算法
青椒大仙KI118 小时前
25/4/6 算法笔记<仿真O2DES>基础知识学习
笔记·学习·算法
井云智能AI矩阵系统8 小时前
数字人情感表达突破:微表情自动生成的算法革新
算法
北冥有鱼被烹8 小时前
【工具】如何将一个脚本作为C语言的一个文件被include到新的C文件中然后执行?(C语言 array的方式)
c语言
旧时光林9 小时前
P10905 [蓝桥杯 2024 省 C] 回文字符串
c语言·c++·蓝桥杯·模拟·枚举