定义:
多态:指相同对象接收到不同消息或者不同的对象接收到相同的消息时产生的不同的动作。
前者,相同的对象接收不同的消息可以看做函数的多态,也就是函数的重载,这种多态是静态的多态,表面上看函数的名称一样,或者由于参数的类型或者个数或者返回值形成的不同的函数重载,在编译器编译的时候,尽管函数名称相同,但是在编译过后会生成不同的函数,这发生在函数运行之前,称之为静态的多态。
如
int max(int a,int b);
int max(int a,int b,int c);
函数名相同,
后者,不同对象接收到相同的消息指的是类的多态。这种多态发生在运行的时候,称之为动态的多态。动态的多态是建立在类的封装和继承的基础上的。首先来看一个例子。
#include <iostream>
#define PI 3.14
using namespace std;
class Base{
public:
double area();
//virtual double area();
};
double Base::area()
{
cout<<"Base area"<<endl;
return 0;
}
class Circle : public Base{
public:
Circle(double r):radies(r){}
double area();
private:
double radies;
};
double Circle::area()
{
cout<<"Circle area“<<endl;
return PI*radies*radies;
}
class Rectangle : public Base{
public:
Rectangle(double len,double wid):length(len),width(wid){}
double area();
private:
double length,width;
};
double Rectangle::area()
{
cout<<"Rectangle area"<<endl;
return length*width;
}
int main(int argc,char *argv[])
{
Base *base1=new Circle(1);
Base *base2=new Rectangle(1,2);
base1->area();
base2->area();
delete base1;
delete base2;
return 0;
}
在这里,用基类的指针Base去指向两个派生类的对象,最后输出的结果是:
也就是说输出的都是基类的area函数中的内容,根本没有多态性。
c++为了实现多态性,采用了一个关键字,就是virtual,将它加在基类的即将要实现多态的函数前,即可实现多态。顺便提一下,在派生类中如果不加virtual 也是可以的,只要基类加了virtual即可,编译器会为我们加上。但是我们一般会在派生类中也添加virtual,是为了使得程序便于阅读,而且也便于派生类再派生一个对象,可以直接看出它含有虚函数。现在将上面的Base 类中的area函数前面加上virtual,就像程序中注释的那样。则输出:
这就是类的多态。基类的指针base1指向一个派生类的对象Circle(1),和Rectangle(1,2),可以分别调用各自派生类对应的函数。这就是c++类的多态性。
虚析构函数:
#include <iostream>
#define PI 3.14
using namespace std;
class Base{
public:
~Base();
// virtual ~Base();
};
Base::~Base()
{
cout<<"~Base"<<endl;
}
//定义一个圆心类,以坐标的形式
class Point{
public:
Point(int x_,int y_):x(x_),y(y_){}
~Point(){cout<<"~point"<<endl;}
private:
int x,y;
};
class Circle : public Base{
public:
Circle(double r);
~Circle();
private:
double radies;
Point *center;
};
Circle::Circle(double r)
{
radies=r;
center=new Point(1,2);
}
Circle::~Circle()
{
delete center;
cout<<"~Circle"<<endl;
}
int main()
{
Base *base=new Circle(1);
delete base;
base=NULL;
return 0;
}
上述定义了一个圆心类,使用动态获取内容的方法。原理:
重载,覆盖和隐藏
#include <iostream>
using namespace std;
class Base{
public:
void f(int x) {cout<<"Base::f(int x)"<<endl;}
void f(double x) {cout<<"Base::f(double x)"<<endl;} //重载f(int x);
virtual void g(int x) {cout<<"Base::g(int x)"<<endl;}
};
class Derived : public Base{
public:
void f(int x) {cout<<"Derived::f(int x)"<<endl;} //隐藏Base::f(int x)
virtual void g(int x) {cout<<"Derived::g(int x)"<<endl;} //覆盖Base::g(int x)
};
int main()
{
Base base;
Derived derived;
base.f(1);
base.f(1.0);
base.g(1);
derived.g(1);
base.f(1);
derived.f(1);
derived.f(1.0);
}
结果:#include<iostream>
#include<string>
using namespace std;
class A
{
public :
A(){}
void f(){cout<<'a'<<endl;}
virtual void g(){cout<<"invoke aaa"<<endl;}
};
class B:public A
{
public:
B(){}
virtual void g(){cout<<"invoke bbb"<<endl;}
void f(){cout<<'b'<<endl;}
};
int main()
{
A * a = new B;
A * b = new A;
B * c = new B;
a->f();
b->f();
c->f();
cout<<"-------------------------"<<endl;
a->g();
b->g();
c->g();
}
结果是
a
a
b
invoke bbb
invoke aaa
invoke bbb
说明:如果是隐藏的话,用指针调用这个函数,根据的是指针自己的类型纯虚函数和抽象类
class Base{
public:
virtual area()=0;
}
如,area()就是纯虚函数,Base类就是抽象类。