C++的多态

什么是多态?

答:多态就是多种形态,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;

}

不是所以的虚函数都要在虚表中找(构成多态才需要)

class A
{
public:
	
	virtual void f1(){}
public:
	int _a;
};
class B : public A
{
	virtual void f1(){}

public:
	int _b;
};
class C : public A
{

public:
	int _c;
};
class D : public B, public C
{

public:
	int _d;
};

int Test()
{
	//构成多态所以要到虚表中找
	A* p=new A;
	p->f1();
	//不构成多态直接找到f1
	A a;
	a.f1();
	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);
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值