一、概念
多态性可以简单的概括为“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;
}
最好把基类的析构函数定义为虚函数:
用对象指针来调用一个函数,有以下两种情况:
如果是虚函数,会调用派生类中的版本。
- 如果是非虚函数,会调用指针所指类型的实现版本。
析构函数也会遵循以上两种情况,因为析构函数也是函数嘛,不要把它看得太特殊。 当对象出了作用域或是我们删除对象指针,析构函数就会被调用。
当派生类对象出了作用域,派生类的析构函数会先调用,然后再调用它父类的析构函数, 这样能保证分配给对象的内存得到正确释放。
但是,如果我们删除一个指向派生类对象的基类指针,而基类析构函数又是非虚的话, 那么就会先调用基类的析构函数,派生类的析构函数得不到调用
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>