注:以下所有代码均是在VS2010环境下测试结果
1、多态引入---->数据的类型
我们知道,不论我们定义一个怎么样的数据或者对象,我们都不会忘了它的类型,那么类型到底充当了一个怎样的角色呢?
数据类型在数据结构中的定义是一个值的集合以及定义在这个值集上的一组操作。变量是用来存储值的所在处,它具有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。在我看来,数据类型就好比一把尺子,它为我们在内存中存储数据提前做好了量度,告诉我们应该占用多大的内存。
举例说明:
2、多态的概念
所谓的多态性,就是不同的对象收到相同的消息时,产生不同的动作。直白点说,就是一个名字定义不同的函数,这些函数执行不同但又类似的操作,从而可以使用相同的方式来调用这些具有不同功能的同名函数,即“一个接口,多种方法”。
静态多态举例:重载函数、模板等
动态多态举例:虚函数等
虚函数的引入:在C++中,基类的对象指针可以指向它公有派生的对象,但是当其指向公有派生类对象时,它只能访问派生类中从基类继承来的成员,而不能访问公有派生类中定义的成员。
使用virtual关键字修饰类的成员函数时,指明该函数为虚函数,派生类需要重新实现,编译器将实现动态绑定。
eg:
class Base
{
public:
Base(int x,int y)//构造函数
{
a = x;
b = y;
}
virtual void show()//虚函数
{
cout<<"Base::"<<a<<" "<<b<<endl;
}
private:
int a;
int b;
};
class Derived:public Base
{
public:
Derived(int x,int y,int z):Base(x,y)//派生类的构造函数(为基类构造函数传参)
{
c = z;
}
void show()//重新定义虚函数show
{
cout<<"Derived::"<<c<<endl;
}
private:
int c;
};
int main()
{
Base b(60,60);//创建基类对象b
Base *pb;//创建基指针类pb
Derived d(10,20,30);//创建派生类对象d
pb = &b;//对象指针指向基类对象b
pb->show();//调用基类的虚函数show()
pb = &d;//对象指针指向派生类对象d
pb->show();//调用派生类的虚函数show()
system("pause");
return 0;
}
【动态绑定条件】
1、必须是虚函数
2、通过基类类型的引用或者指针调用虚函数
两个条件必须同时满足才可形成动态绑定
虚函数总结:
<1>由于虚函数使用的基础是赋值兼容规则,而赋值兼容规则的前提条件是派生类从其基类公有派生,所以使用虚函数来实现多态时,派生类必须从它的基类公有派生。
<2>必须首先在基类中定义虚函数。
<3>在派生类中对基类中声明的虚函数进行重定义时,关键字virtual可以加也可以不加。为了不引起混乱,最好加上。
<4>虽然使用对象名和点运算符的方式也可以调用虚函数,但只有通过基类指针或引用访问虚函数时才能获得运行时的多态性。
<5>一个虚函数无论被继承多少次,它仍然保持其虚函数的特性。
<6>虚函数必须是其所在类的成员函数,而不能是友元函数,也不能是静态成员函数。
<7>内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。
<8>构造函数不能是虚函数,但是析构函数可以是虚函数,而且通常说明为虚函数。
3、函数重载&同名隐藏&重写:
函数重载:
//函数重载
int add(int x,int y)
{
return x+y;
}
double add(float a,float b)
{
return a+b;
}
int main()
{
int a = 3,b = 5;
float x = 3.14f,y = 6.8f;
int ret1 = add(a,b);
cout<<"int----"<<ret1<<endl;
double ret2 = add(x,y);
cout<<"double----"<<ret2<<endl;
system("pause");
return 0;
}
运行结果:
重写举例:
//重写
class Base
{
public:
virtual void show(int x,int y)//虚函数
{
a = x;
b = y;
cout<<"Base::"<<a<<" "<<b<<endl;
}
private:
int a;
int b;
};
class Derived:public Base
{
public:
void show(int x,int y)//重新定义虚函数show
{
c = x + y;
cout<<"Derived::"<<c<<endl;
}
private:
int c;
};
int main()
{
Base b;//创建基类对象b
Derived d;//创建派生类对象d
b.show(10,20);
d.Derived::s