C++多态的使用

在学习本章时我们一定要注意代码段我标明的注释

1.多态使用条件

1.必须用基类的引用或者指针去调用虚函数

 2.被调用的函数必须是虚函数,而且完成了重写/覆盖

using namespace std;
#include<iostream>
class person
{
public:
	virtual void Buyticket()//重写 virtual是关键字,用来定义虚函数
	{
		cout << "全价购票" << endl;
	}
private:
	int ID;
};
class student : public person
{
public:
	virtual void Buyticket()//重写 virtual是关键字,用来定义虚函数
	{
		cout << "半价购票" << endl;
	}
private:
	int IDcard;
};
int main()
{
	student ST;
	person* PS = &ST;//用基类的指针或引用调用虚函数
	PS->Buyticket();
}

1.虚函数

在内部成员函数名前面加virtual关键字,那么这个函数便成了这个类的虚函数 

 

2.虚函数的重写与覆盖 

多态的构成需要各个派生类和基类都重写虚函数

重写就是,在子类里面写一个与父类要实现多态的函数名相同的函数

3.虚函数的细节问题 

当我们不再子类里写virtual时我们同样能构成多态 

using namespace std;
#include<iostream>
class person
{
public:
	virtual void Buyticket()
	{
		cout << "全价购票" << endl;
	}
private:
	int ID;
};
class student : public person
{
public:
	void Buyticket()
	{
		cout << "学生半价购票" << endl;
	}
private:
	int IDcard;
};
class adult :public person
{
public:
	void Buyticket()
	{
		cout << "成人全价购票" << endl;
	}
private:
	int creditcard;
};
int main()
{
	student ST;
	person* PS = &ST;//用基类的指针或引用调用虚函数
	adult ad;
	person* PS1 = &ad;
	PS->Buyticket();
	PS1->Buyticket();
}

不过这种实现会有缺陷,我们来看一个代码

class A
{
public:
	virtual void func(int val = 1) 
	{
		std::cout << "A->" << val << std::endl;
	}
	virtual void test() 
	{ 
		func(); 
	}
};
class B : public A
{
public:
	void func(int val = 0) 
	{
		std::cout << "B->" << val << std::endl;
	}
};
int main()
{
	B* p = new B;
	p->test();
	return 0;
}

按照我们之前的思想这个代码是不是应该输出的是B->0才对 

不过因为我们没有在子类函数加virtual所以导致了这种情况 

因为如果我们不加virtual那么继承方式如下图所示 

 

因为B的函数不是虚函数,所以在继承时会把A的函数体替换B 

 4.析构函数的重写

子类继承父类,它们的析构函数会构成重写,因为编译器对析构函数做了特殊处理,在编译时会将析构函数统一处理成destructor。所以它们的函数名相同。

所以当我要使用多态时重新写类的析构函数时我们需要在析构函数前加virtual,否则在程序结束后,将不会调用子类的析构函数,从而导致内存泄漏 

class A
{
public:
	~A()
	{
		cout << " ~A() " << endl;
	}
};
class B : public A
{
public:
	~B()
	{
		cout << " ~B() " << endl;
	}
};
int main()
{
	A* p1 = new B;
	A* p2 = new A;
	delete p1;
	delete p2;
}

class A
{
public:
	virtual~A()
	{
		cout << " ~A() " << endl;
	}
};
class B : public A
{
public:
	~B()
	{
		cout << " ~B() " << endl;
	}
};
int main()
{
	A* p1 = new B;
	A* p2 = new A;
	delete p1;
	delete p2;
}

 5.override和final

 1.override

用法:判断一个子类的函数是否与父类构成重写

 

2.final 

用法:使一个函数不能被重写

 

 6.纯虚函数和抽象类

 

在需要设置纯虚函数后面写=0,那么这个函数就被定义为纯虚函数(不需要被实现,没什么意义),纯虚函数需要在被派生类继承时才定义,拥有纯虚函数的类叫做抽象类,而抽象类不能实现对象,所以派生类想要定义对象,必须帮助基类去实现纯虚函数。

 PS:多态的原理,记住虚函数表和虚函数指针

多态是面向对象编程的三大特性之一(封装、继承、多态),在 C++ 中主要通过虚函数(`virtual`)实现。多态允许我们使用基类指针或引用调用派生类的方法,实现运行时动态绑定。 下面是一个完整的 C++ 多态使用实例,演示如何通过基类指针调用不同子类的重写方法。 ### 示例代码 ```cpp #include <iostream> using namespace std; // 基类 class Animal { public: // 虚函数实现多态 virtual void speak() { cout << "Animal speaks" << endl; } // 虚析构函数,确保派生类析构函数被调用 virtual ~Animal() {} }; // 派生类 Dog class Dog : public Animal { public: void speak() override { cout << "Woof!" << endl; } }; // 派生类 Cat class Cat : public Animal { public: void speak() override { cout << "Meow!" << endl; } }; int main() { Animal* animal1 = new Dog(); // 基类指针指向派生类对象 Animal* animal2 = new Cat(); animal1->speak(); // 调用 Dog::speak() animal2->speak(); // 调用 Cat::speak() delete animal1; delete animal2; return 0; } ``` ### 代码解释: - **`virtual void speak()`**:在基类 `Animal` 中声明为虚函数,表示该函数可以在派生类中被重写。 - **`override`**:在 `Dog` 和 `Cat` 类中使用 `override` 关键字明确表明这是对基类虚函数的覆盖。 - **运行时多态**:通过基类指针调用 `speak()` 时,程序会在运行时根据实际对象类型调用相应的函数。 - **虚析构函数**:为了确保在删除基类指针时能正确调用派生类的析构函数,避免内存泄漏,基类的析构函数声明为虚函数。 ### 输出结果: ``` Woof! Meow! ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值