c++多态

目录

一、定义

二、多态的定义及实现

(一)多态的构成条件

(二)继承中要构成多态有2个条件

(三)虚函数

 (四)虚函数的重写

1. 概念

2. 虚函数重写的两个例外

2.1 协变

2.2  析构函数的重写

2.3 重载、覆盖(重写)、隐藏(重定义)的对比

三、多态原理

(一)虚函数表

(二)单继承中的虚函数表


一、定义

多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会
产生出不同的状态

二、多态的定义及实现

(一)多态的构成条件

  • 多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价

(二)继承中要构成多态有2个条件

  • 虚函数重写
  • 父类的指针或者引用去调用虚函数

(三)虚函数

  • 虚函数:即被virtual修饰的类成员函数称为虚函数
class Person 
{
    public:
        virtual void BuyTicket() { cout << "买票-全价" << endl;}
};

 (四)虚函数的重写

1. 概念

  • 父子继承关系的两个虚函数,要求三同返回值类型、函数名称、参数列表均相同)
  • virtual只能修饰成员函数
  • 注意:三同(函数名/参数/返回值)中有个例外,返回值可以不同,但是必须是父子关系的指针或引用
class Person 
{
	public:
		virtual void BuyTicket() 
		{ 
			cout << "买票-全价" << endl; 
		}
};
class Student : public Person 
{
	public:
		virtual void BuyTicket() 
		{ 
			cout << "买票-半价" << endl;
		}
};

c++多态_第1张图片

2. 虚函数重写的两个例外

2.1 协变
  • 协变(基类与派生类虚函数返回值类型不同)
  • 派生类重写基类虚函数时,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为协变

class A//父类
{
	public:
		virtual A* fun()
		{
			cout << "virtual A* fun()" << endl;
			return nullptr;
		}
};

class B:public A
{
	public:
		virtual B* fun()
		{
			cout << "virtual B* fun()" << endl;
			return nullptr;
		}
};

c++多态_第2张图片

2.2  析构函数的重写
#include
using namespace std;

class Person 
{
	public:
		~Person()
		{
			cout << "~Person()" << endl;
		}
};
class Student : public Person 
{
	public:
		~Student()
		{
			cout << "~Student()" << endl;
		}
};


int main()
{
	Person* ptr1 = new Person;//new一个父类的对象,交给父类的指针管理
	delete ptr1;

	Person* ptr2 = new Student;//new一个子类的对象,交给父类的指针管理
	delete ptr2;

	return 0;
}

c++多态_第3张图片

加上virtual :

class Person 
{
	public:
		virtual ~Person()
		{
			cout << "~Person()" << endl;
		}
};
class Student : public Person 
{
	public:
		virtual ~Student()
		{
			cout << "~Student()" << endl;
		}
};

c++多态_第4张图片

2.3 重载、覆盖(重写)、隐藏(重定义)的对比

c++多态_第5张图片

三、多态原理

(一)虚函数表

例如:下面sizeof(Base)是多少?

#include
using namespace std;

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

private:
	int _b = 1;
	char _c;
};

int main()
{
	Base b;
	cout << sizeof(Base) << endl;//12
	return 0;
}

c++多态_第6张图片

#include
using namespace std;
class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票-全价" << endl;
	}
	virtual void fun(){}
private:
	int a = 0;
};
class Student : public Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票-半价" << endl;
	}
private:
	int b = 1;
};
void Func(Person& p)
{
	p.BuyTicket();
}
int main()
{
	Person p;
	Student s;
	Func(p);
	Func(s);
	return 0;
}

c++多态_第7张图片

(二)单继承中的虚函数表

c++多态_第8张图片

c++多态_第9张图片

#include
using namespace std;

class Base {
public:
	virtual void func1() { cout << "Base::func1" << endl; }
	virtual void func2() { cout << "Base::func2" << endl; }
private:
	int a;
};
class Derive :public Base {
public:
	virtual void func1() { cout << "Derive::func1" << endl; }
	virtual void func3() { cout << "Derive::func3" << endl; }
	virtual void func4() { cout << "Derive::func4" << endl; }
private:
	int b;
};

typedef void(*VFPTR) ();
//等价形式void PrintVTable(VFPTR* a)
void PrintVTable(VFPTR a[])
{
	// 依次取虚表中的虚函数指针打印并调用。调用就可以看出存的是哪个函数
	cout << " 虚表地址>" << a << endl;
	for (int i = 0; a[i] != nullptr; ++i)
	{
		printf(" 第%d个虚函数地址 :0X%x,->", i, a[i]);
		VFPTR f = a[i];
		f();
	}
	cout << endl;
}
int main()
{
	Base b;
	Derive d;

	VFPTR * vTableb = (VFPTR*)(*(int*)&b);
	PrintVTable(vTableb);

	VFPTR* vTabled = (VFPTR*)(*(int*)&d);
	PrintVTable(vTabled);
	return 0;
}

你可能感兴趣的:(c++,面向对象编程c++,c++,开发语言)