C++中的虚函数与多态

1 虚函数与虚函数表

   虚函数:用virtual修饰的成员函数

   虚函数表:就是一个指针存储所有虚函数的首地址

#include <iostream>
using namespace std;

class student
{
public:
	void print()//普通函数不影响类的内存
	{
		cout << "普通函数" << endl;
	}
	virtual void print1()//虚函数类的内存增加,不论几个增加不变
	{//32位操作系统增加4字节,64位8字节
		cout << "虚函数" << endl;
	}
	virtual void print2()
	{
		cout << "虚函数2" << endl;
	}
	virtual void print3();
protected:
};
void student::print3()
{
	cout << "在类内定义虚函数,在类外实现" << endl;
}
void testVirtual()
{//C语言不允许存在空的结构体
	cout << sizeof(student) << endl;
	student A;
	int** vptr = (int**)&A;
	typedef void(*PF)();
	PF func = (PF)vptr[0][0];
	func();//虚函数表调用第一个虚函数
	func = (PF)vptr[0][1];
	func();//虚函数表调用第二个虚函数
}//C++允许存在空的类或结构体,占1字节

int main()
{
	testVirtual();
	return 0;
}

2虚函数和多态

定义:同一个调用的不同结果为多态

必要性原则:父类必须存在虚函数,子类必须采用公有继承  ,必须存在指针的引用。

class student
{
public:
	void print1()
	{
		cout << "是学生1" << endl;
	}
	virtual void print2()//父类必须有virtual
	{
		cout << "是学生2" << endl;
	}
protected:

};
class teacher:public student//公有继承
{
public:
	void print1()
	{
		cout << "是老师1" << endl;
	}
	void print2()//子类要存在一个同名函数
	{
		cout << "是老师2" << endl;
	}
protected:

};
void testVirtual()
{
	//正常访问不存在多态,就近原则
	student A;
	A.print1();
	A.print2();
	teacher B;
	B.print1();
	B.print2();
	//指针访问,正常赋值
	student* ps = new student;
	ps->print1();
	ps->print2();
	teacher* pt = new teacher;
	pt->print1();
	pt->print2();
	//指针非正常赋值:子类对象初始化父类指针
	student* Ps = new teacher;
	Ps->print1();//非虚函数
	Ps->print2();//虚函数,父类调用子类同名函数
}

3 纯虚函数与ADT

纯虚函数也是一个虚函数,但没有函数体

抽象类:具有至少一个纯虚函数的类

抽象类不能构建对象,但可以构建对象指针

class parent
{
public:
	virtual void print() = 0;//纯虚函数写法
protected:

};
void textVirtual()
{
	//parent A;//报错抽象类不能构建对象
	parent* P = nullptr;//可以构建指针
}
//纯虚函数就是做ADT(abstract data type)抽象数据类型的额过程
class stack
{
public://父类中描述好所有的属性
	virtual void push(int data) = 0;
	virtual void pop() = 0;
	virtual void top()const = 0;
	virtual bool empty()const = 0;
	virtual int size() = 0;
};
class arryStack :public stack
{
public:
};
class listStack :public stack
{
public:
};

4 虚析构函数

class parent
{
public:
	virtual ~parent()
	{
		cout << "父类析构" << endl;
	}
	void print()
	{

	}
protected:

};
class son:public parent
{
public:
	~son()
	{
		cout << "子类析构" << endl;
	}
	void print()
	{

	}
protected:
};
int main()
{//在用子类初始化父类指针,父类需要析构函数做内存释放
	parent* P = new son;
	P->print();
	delete P;
	P = nullptr;
	return 0;
}

5 C++类型转换与两个关键字

 

//两个关键字  final  override
class A
{
public:
	virtual void print()final//
	{//加final后子类不能存在同名函数
		//限制子类不能重写这个函数
		//孙子类也不行!!
		cout << "重写虚函数才有" << endl;
	}
	virtual void printData()
	{

	}
protected:

};
class B :public A
{
public:
	//void print()
	void printData()override
	{//强制重写标识作用,用于检查父类是否存在当前的虚函数
		cout << "表示当前函数是重写函数" << endl;
	}
};


class A
{
public:
	A(const char* str) :str(const_cast<char*>(str)) {}
protected:
	char* str;
};
class B
{
public:
	B(int num) :num(num) {}
protected:
	int num;
};
int main()
{
	//const_cast
	//const_cast<要转换的类型>(要转换的目标)
    //作用1去掉const属性 2加上const属性
	const int num = 9;
	int* Pnum = const_cast<int*>(&num);
	*Pnum = 99;
	cout << num << endl;
	A a("jsbd");
	char c[] = "lskd";
	A b(c);
	const B* pB = new B(0);
	B* Pb = const_cast<B*>(pB);
	int num;
	const int& pnum = num;
	int& Pnum = const_cast<int&>(pnum);
	int a1 = 99;
	int* Pa = &a1;
	const int* pA = Pa;
	//static_cast
	//static_cast<要转换的类型>(要转换的目标)
	//基本数据类型转换,把任何类型的变量转换为void类型
	//用在类上面改的转换(基本和派生类对象之间的转换)
	char str = 'A';
	int istr = static_cast<int>(str);
	cout << istr << endl;
	double* pD = new double;
	void* pD1 = static_cast<void*>(pD);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值