什么是多态?
答:多态就是多种形态,c++的多态分为静态多态和动态多态。
1.静态多态就是重载,因为是编译期决定所以称为静态多态.
2.动态多态就是通过继承重写基类的虚函数实现多态,因为是运行时决定的所有称为动态多态.
1.多态的实现— —虚表
1.1虚函数
c++中虚函数的主要作用就是实现多态.简单来说父类的指针/引用调用重写的虚函数,当父类的指针/引用指向父类对象时调用的就是父类的虚函数,指向子类对象时就是调用子类的虚函数.
例:
#include<iostream>
#include<stdlib.h>
using namespace std;
class A
{
public:
virtual void f1()
{
cout << "父类的虚函数f1()" << endl;
}
private:
int _a;
};
class B:public A
{
public:
virtual void f1()
{
cout << "子类的虚函数f1()" << endl;
}
private:
int _b;
};
int main()
{
B b;
b.A::f1(); //父类指针指向父类对象
b.B::f1(); //父类指针指向子类对象
system("pause");
return 0;
}
1.2虚函数表
虚函数表是通过一块连续内存来储存虚函数的地址.这张表解决了继承,虚函数重写的问题,在有虚函数的对象实例中都存在一张虚函数表,虚函数表就像一张地图,指明了实际调用的虚函数.
1.2.1 单继承的虚函数表
.h
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
class Base
{
public:
virtual void f1()
{
cout << "Base::f1" << endl;
}
virtual void f2()
{
cout << "Base::f2" << endl;
}
private:
int _a;
};
class Derive
{
public:
virtual void f1()
{
cout << "Derive::f1" << endl;
}
virtual void f3()
{
cout << "Derive::f3" << endl;
}
virtual void f4()
{
cout << "Derive::f4" << endl;
}
private:
int _b;
};
typedef void(*FUNCT)();
void PrintfTable(int* Table)
{
cout << "虚表地址" << Table << endl;
for (int i = 0; Table[i] != 0; ++i)//虚函数表是以0表示结束
{
printf("第%d个虚函数地址:0X%x,->", i, Table[i]);
FUNCT f = (FUNCT)Table[i];
f();
}
cout << endl;
}
void Test()
{
Base b;
Derive d;
int* Table1 = (int*)(*(int*)&b);
int* Table2 = (int*)(*(int*)&d);
PrintfTable(Table1);
PrintfTable(Table2);
}
.cpp
#include"test.h"
int main()
{
Test();
system("pause");
return 0;
}
不是所以的虚函数都要在虚表中找(构成多态才需要)
![]() |
1.2.2 多继承的虚函数表
.h
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
class Base1
{
public:
virtual void f1()
{
cout << "Base::f1" << endl;
}
virtual void f2()
{
cout << "Base::f2" << endl;
}
private:
int _a1;
};
class Base2
{
public:
virtual void f1()
{
cout << "Base2::f1()" << endl;
}
virtual void f2()
{
cout << "Base2::f2()" << endl;
}
private:
int _a2;
};
class Derive :public Base1, public Base2
{
public:
virtual void f1()
{
cout << "Derive::f1()" << endl;
}
virtual void f3()
{
cout << "Derive::f3()" << endl;
}
private:
int _b;
};
typedef int (*VFUNC)();
void PrintVTable(int * table)
{
cout<<"虚表地址>"<<table<<endl;
for (int i = 0; table[i] != 0; i++)
{
printf("第%d个虚函数地址:0X%x,->",i,table[i]);//虚表指针是以0表示结尾的(有_a1,_a2,_b和张虚表指针)5*4=20
VFUNC f = (VFUNC)table[i];
f();
}
}
void Test()
{
Derive d1;
cout << sizeof(d1) << endl;//20
PrintVTable((int*)(*((int*)&d1)));
PrintVTable((int*)(*((int*)((char*)&d1+sizeof(Base1)))));
}
.cpp
#include"test.h"
int main()
{
Test();
system("pause");
return 0;
}
class A { public: virtual ~A(){}; virtual void f1(){}; }; class B { public: virtual void f2(){}; }; class C:public B,public A { public: }; void Test() { C c; A* p1 = &c; B* p2 = &c; C* p3 = &c; cout << p1 << endl; cout << p2 << endl; cout << p3 << endl; } 关于p1,p2,p3取值,下面描述正确的是(B) A p1,p2,p3取值相同 B p1和p3不相同 Cp2和p3不相同 D p3不等于p1也不等于p2
|
1.2.3 菱形虚继承的虚函数表
using namespace std;
class A
{
public:
virtual void fa()
{
cout << "A" << endl;
}
virtual void f1(){}
public:
int _a;
};
class B:virtual public A
{
virtual void fb()
{
cout << "B" << endl;
}
public:
int _b;
};
class C :virtual public A
{
virtual void fc()
{
cout << "C" << endl;
}
public:
int _c;
};
class D : public B, public C
{
virtual void f1()
{
cout << "D" << endl;
}
virtual void fd(){}
public:
int _d;
};
void Test()
{
D d;
cout << sizeof(D) << endl;//36
}
菱形虚继承对象模型
1.3多态的分类
1.3.1静态多态
静态多态就是重载,因为是在编译期决议确定,所以称为静态多态。
1.3.2动态态多态
动态多态就是通过继承重写基类的虚函数实现的多态,因为是在运行决议确定的,所以称为动态多态
class Base
{
public:
virtual void f1()
{
cout << "Base::f1()" << endl;
}
virtual void f2()
{
cout << "Base::f2()" << endl;
}
void display()
{
cout << "Base::display()" << endl;
}
void display(int i)
{
cout << "Base::display(int i)" << endl;
}
private:
int _a;
};
class Derive:public Base
{
virtual void f1()
{
cout << "Derive::f1()" << endl;
}
private:
int _b;
};
void func(Base& b)
{
b.f1();
b.display();
b.display(10);
}
void Test()
{
Base b1;
Derive d;
func(b1);
func(d);
}