1、多态是指同一行为不同对象会产生不同结果。

2、多态形成的条件:

(1)虚函数的重写(重写该函数的实现)

(2)父类指针或者引用调用该函数

a、虚函数:

被virtual修饰的函数,父类函数前必须写,派生类不做要求,但建议写上。

多态_虚表

多态_虚函数_02

多态_虚表

注:virtual无法修饰静态函数

       虚函数重写要做到三同:

      函数名参数与返回类型相同

      但有两个例外:

     协变(基类与派生类的返回类型不同)

     析构函数的重写(虽然其函数名不同,但其会被编译器统一处理为destructor的函数名称)

//class Person {
//public:
//	virtual ~Person() 
//	{ 
//		cout << "~Person()" << endl;
//	}
//
//};
//
//class Student : public Person {
//public:
//	~Student() override
//	{
//		delete _ptr;
//		cout << "~Student():"<< _ptr<< endl; 
//	}
//protected:
//	int* _ptr = new int[10];
//};
//
//int main()
//{
//	//Student st;
//
//	Person* p1 = new Student;
//
//	// 实现多态,就正常了
//	// 
//	// p1->destructor() + operator delete(p1)
//	delete p1;
//
//	Person* p2 = new Person;
//	delete p2;
//
//	
//
//	return 0;
//}

3、

多态_虚表_04

4、

多态_虚函数_05

5、虚(函数)表(本质上为虚函数指针数组)

类中的虚函数均存在于指针数组中方便访问

形似:

多态_虚表_06

注意打印地址时,成员函数需加取地址符号并指明类域

class Base
{
public:
	virtual void Func1()
	{
		cout << "Base::Func1()" << endl;
	}

	virtual void Func2()
	{
		cout << "Base::Func2()" << endl;
	}

	void Func3()
	{
		cout << "Base::Func3()" << endl;
	}
private:
	int _b = 1;
};

class Derive : public Base
{
public:
	virtual void Func1()
	{
		cout << "Derive::Func1()" << endl;
	}
private:
	int _d = 2;
};

void Func1(Base* p)
{
	// 运行时绑定/动态绑定
	p->Func1();

	// 编译时绑定/静态绑定
	p->Func3();
}

//int main()
//{
//	Base b;
//	Derive d;
//	
//	Func1(&b);
//	Func1(&d);
//
//	return 0;
//}

//int main()
//{
//	const char* str = "11111111";
//	cout << str << endl;
//
//	Base b;
//
//	printf("%p\n", str);
//	printf("%p\n", &Base::Func1);
//	printf("%p\n", &Base::Func2);
//	printf("%p\n", &Base::Func3);
//
//	int a = 0;
//	printf("%p\n", &a);
//
//	return 0;
//}

总结:

多态_多态_07

6、动态绑定与静态绑定

动:虚函数在多态中的调用,又称运行时绑定

jing:普通函数的选择,又称编译时绑定

7、虚表在常量区

多态_虚表_08

//int main()
//{
//	int i = 0;
//	static int j = 1;
//	int* p1 = new int;
//	const char* p2 = "xxxxxxxx";
//	printf("栈:%p\n", &i);
//	printf("静态区:%p\n", &j);
//	printf("堆:%p\n", p1);
//	printf("常量区:%p\n", p2);
//
//	Base b;
//	Derive d;
//
//	// int/double/char
//	// int和int*  指针之间
//	printf("Base虚表地址:%p\n", *((int*)&b));
//	printf("Derive虚表地址:%p\n", *((int*)&d));
//	printf("Base对象地址:%p\n", &b);
//	printf("Derive对象地址:%p\n", &d);
//
//	Base b1;
//	Base b2;
//	Base b3;
//
//	return 0;
//}