多态表现出来的现象就是:父类的指针指向谁的对象就调用谁;
一。区分 函数重载,重写(同名隐藏),重定义(覆盖) ,协变;
函数重载
同一作用域
相同函数名,不同参数(类型,数量,顺序)
返回值不限
重写(同名隐藏)
不同作用域
函数名相同
重定义
不同作用域
函数名,参数列表,返回值统统相同
基类函数必须加virtual关键字
构成多态必须要满足以下两点要求;
1,重定义
2,父类的指针指向子类的对象
二。下面给出实例
1,既构不成多态,父类指针也没有指向子类;
class Base
{
public:
void f1()
{
cout << " f1():base()" << endl;
}
/*virtual void f2()
{
cout << " f2():base()" << endl;
}*/
protected:
int _b;
};
class Drive :public Base
{
public:
virtual void f1()
{
cout << " f1():drive()" << endl;
}
/*void f2()
{
cout << " f2():drive()" << endl;
}*/
protected:
int _d;
};
int main()
{
Base b;
Drive d;
b.f1();
d.f1();
//Base* p = &b;
p=&d;
//p->f();
return 0;
}
2,子类函数前加virual关键字,父类不加,父类指针指向子类;(构不成多态)
class Base
{
public:
void f1()
{
cout << " f1():base()" << endl;
}
/*virtual void f2()
{
cout << " f2():base()" << endl;
}*/
protected:
int _b;
};
class Drive :public Base
{
public:
virtual void f1()
{
cout << " f1():drive()" << endl;
}
/*void f2()
{
cout << " f2():drive()" << endl;
}*/
protected:
int _d;
};
int main()
{
/*b.f1();
d.f1();*/
Base b;
Drive d;
Base* p = &b;
p->f1();
p=&d;
p->f1();
return 0;
}
结果和上面一模一样
3,延续第二种情况,将子类的virtual关键字加到父类;(构成多态)
总结;先看有没有构成多态,必须满足这两点,1,构成重写,2,父类指针指向子类 ,
由例2和例3可以看出奇遇不变只要将子类的关键字加到父类之前就构成了多态,如果其他条件都满足,只想加一个virtual构成多态,必须加到父类父类上;
如果不能构成多态,调用子类还是父类的函数由所调函数的对象或者是指针决定;父类对象或指针调用的就是父类成员函数,子类对象或指针调用的就是子类的成员函数,
如果构成多态,则父类的指针指向谁就调用谁的成员函数;
三。揭秘多态的底层面纱
其实
不通过内存窗口而是在屏幕上打印出程序的底层,
#include<iostream> using namespace std; class Base1 { public: virtual void f1() { cout << " base1:f1()" << endl; } virtual void f2() { cout <<" base1:f2()" << endl; } protected: int _b; }; class Base2 { public: virtual void y1() { cout << "base2: y1()" << endl; } virtual void y2() { cout << " base2:y2()" << endl; } protected: int _b2; }; class Drive :public Base1, public Base2 { public: virtual void f1() { cout << " drive:f1()" << endl; } void z1() { cout << " drive:z1()" << endl; } virtual void z2() { cout << " drive:z2()" << endl; } protected: int _d; }; typedef void(*v_FUNC)(); void PrintVTable(Base1 &b1) { v_FUNC vTable = (v_FUNC)*(int*)(*(int*)(&b1)); int i = 0; while (vTable) { i++; vTable(); vTable = (v_FUNC)(*((int *)(*(int*)(&b1)) + i)); } cout << endl; } typedef void(*v_FUNC)(); void PrintVTable(Base2 &b2) { v_FUNC vTable = (v_FUNC)*(int*)(*(int*)(&b2)); int i = 0; while (vTable) { i++; vTable(); vTable = (v_FUNC)(*((int *)(*(int*)(&b2)) + i)); } cout << endl; } typedef void(*v_FUNC)(); void PrintVTable(Drive &d) { v_FUNC vTable = (v_FUNC)*(int*)(*(int*)(&d)); int i = 0; while (vTable) { i++; vTable(); //printf("%p\n", &vTable);//为什莫地址每次是随机的一致; vTable = (v_FUNC)(*((int *)(*(int*)(&d)) + i)); } } int main() { /*b.f1(); d.f1();*/ Base1 b1; Base2 b2; Drive d; /*Base* p = &b; p->f1(); p=&d; p->f1();*/ PrintVTable(b1); PrintVTable(b2); PrintVTable(d); return 0; }
运行结果;
多继承中,子类新的成员函数保存在先被继承的父类的虚函数表中;