多态

一、概念

多态性可以简单的概括为“1个接口,多种方法”,在程序运行的过程中才决定调用的机制
程序实现上是这样,通过父类指针调用子类的函数,可以让父类指针有多种形态。

二、形式

静态多态(函数重载)模板函数 编译时就可以确定对象使用的形式

动态多态(虚函数,函数重写)其具体引用的对象在运行时才能确定


三、函数重载实现的多态

函数重载:函数名相同,参数不同

#include<iostream>
using namespace std;
void test(int a)
{
	cout<<a<<endl;
}
void test(char* s)
{
	cout<<s<<endl;
}
int main()
{
	int a=1;
	char* s="hello world";
	test(a);
	test(s);
	system("pause");
	return 0;
}
虚函数实现的多态

#include<iostream>
#include<string>
using namespace std;
class person
{
public:
	person(const char* name,const char* sex,int age)
		:_name(name)
		,_sex(sex)
		,_age(age)
	{
		cout<<"person()"<<endl;
	}
	 virtual void Display()
	{
		cout<<"name:"<<_name<<"sex:"<<_sex<<"age:"<<_age<<endl;
	}
     virtual ~person() //析构函数为虚函数
	{
		cout<<"~person"<<endl;
	}
private:
	string _name;
	string _sex;
	int _age;
};
class teacher :public person
{
public:
	teacher(const char* name,const char* sex,int age,const char* subject)
		:person(name,sex,age)
	    ,_subject(subject)
	{
		cout<<"teacher()"<<endl;
	}
	~teacher()
	{
		cout<<"~teacher"<<endl;
	}
	void Display()
	{
		cout<<"subject:"<<_subject<<endl;
	}
private:
	string _subject;
};
void fun(person& p) //实现多态
{
	p.Display();
}
void test()
{
	//person p1("zyc","女",20);
	//teacher t1("www","nan",23,"math");
	//fun(p1);
	//fun(t1);

	//person* p=new teacher("lulu","nv",23,"yuyan");
	//delete p;  //通过指针访问时,必须动手delete释放;

	teacher* t=(teacher*)new person("lala","nan",12); //子类指针指向父类,必须强转
	delete t;

}
int main()
{
	test();
	system("pause");
	return 0;
}
最好把基类的析构函数定义为虚函数:

用对象指针来调用一个函数,有以下两种情况:

如果是虚函数,会调用派生类中的版本。

  1. 如果是非虚函数,会调用指针所指类型的实现版本。

析构函数也会遵循以上两种情况,因为析构函数也是函数嘛,不要把它看得太特殊。 当对象出了作用域或是我们删除对象指针,析构函数就会被调用。

当派生类对象出了作用域,派生类的析构函数会先调用,然后再调用它父类的析构函数, 这样能保证分配给对象的内存得到正确释放。

但是,如果我们删除一个指向派生类对象的基类指针,而基类析构函数又是非虚的话, 那么就会先调用基类的析构函数,派生类的析构函数得不到调用

class person
{
public:
	person(const char* name,const char* sex,int age)
		:_name(name)
		,_sex(sex)
		,_age(age)
	{
		cout<<"person()"<<endl;
	}
	 virtual void Display()
	{
		cout<<"name:"<<_name<<"sex:"<<_sex<<"age:"<<_age<<endl;
	}
     ~person() //析构函数不为虚函数
	{
		cout<<"~person"<<endl;
	}
private:
	string _name;
	string _sex;
	int _age;
};
class teacher :public person
{
public:
	teacher(const char* name,const char* sex,int age,const char* subject)
		:person(name,sex,age)
	    ,_subject(subject)
	{
		cout<<"teacher()"<<endl;
	}
	~teacher()
	{
		cout<<"~teacher"<<endl;
	}
	void Display()
	{
		cout<<"subject:"<<_subject<<endl;
	}
private:
	string _subject;
};
void fun(person& p) //实现多态
{
	p.Display();
}
void test()
{
	//person p1("zyc","女",20);
	//teacher t1("www","nan",23,"math");
	//fun(p1);
	//fun(t1);

	person* p=new teacher("lulu","nv",23,"yuyan");  //第一种情况
	delete p;  //通过指针访问时,必须动手delete释放;
   
	teacher* t=(teacher*)new person("lala","nan",12); //第二种情况:子类指针指向父类,必须强转
	delete t;

}
int main()
{
	test();
	system("pause");
	return 0;
}

结果:

当基类析构函数不为虚函数时,

第一种情况:构造函数没错,调用析构函数指针类型的版本



第二种情况:调用了~teacher;发生中断

因此,将基类的虚函数声明为虚函数,他的所有派生类析构函数都为虚函数,删除一个指向派生类的基类指针时,析构函数会正确调用。

模板函数实现多态:

<span style="color:#333333;">#include<iostream>
using namespace std;
template <class T>
T compare(T num1,T num2) 
{
	return num1>num2 ? num1 :num2;
}
template<>
char* compare(char* s1,char* s2)
{
	return (strcmp(s1,s2) ? s1:s2);
}
int main()
{
	char* s1="lala";
	char* s2="nihao";
	char *ret=compare(s1,s2);
	int num=compare(3,4);
	cout<<ret<<endl;
	cout<<num<<endl;
	system("pause");
	return 0;
}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值