C++虚函数和多态

1 虚函数

        1.1  定义 用virtual修饰的成员函数叫 虚函数

        1.2 对类内存影响

                空的类(类内没有数据成员,成员函数不占用内存)占用1字节

                        有虚函数的占用4字节(32位),也就是一个指针的大小

                        无论有多少个虚函数都是占用4字节。

                类外实现不需要virtual修饰

#include<iostream>
using namespace std;
class A
{
public:
	void print() {}
protected:
};
class B
{
public:
	virtual void print() {}
protected:
};
void testVitrual()
{
	cout << sizeof(B) << endl;
}
void testA()
{
	cout << sizeof(A )<< endl;
}

int main()
{
	testA();
	testVitrual();

	return 0;
}

        1.3 虚函数表

                就是一个指针,存放了所有虚函数的首地址。

#include<iostream>
using namespace std;
class A
{
public:
	virtual void print1() {cout<<"虚函数1"<<endl;}
	virtual void print2() { cout << "虚函数2" << endl; }
	virtual void print3() {}
protected:
};

void testA()
{
	A a;
	int** vptr = (int**)&a;
	typedef void(*PF)();
	PF func = (PF)vptr[0][0];
	func();
	func = (PF)vptr[0][1];
	func();
}

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

 2 多态

        2.1 定义 同一种行为(调用)导致不同 的结果

        2.2 必要性原则

                必须父类存在虚函数(子类有无virtual都可,但必须有同名函数)

                子类必须采用public继承

                必须存在指针的引用(使用)

#include <iostream>
using namespace std;
class Man
{
public:
	void print1()
	{
		cout << "阿郎" << endl;
	}
	virtual void print2()   //父类必须要有virtual
	{
		cout << "阿郎呀呀" << endl;
	}
protected:
};
class Sister :public Man
{
public:
	void print1()
	{
		cout << "阿妹" << endl;
	}
	void print2()
	{
		cout << "阿妹妹呀" << endl;
	}
protected:

};
void testVirtual()
{
	//正常访问不存在多态
	cout << "正常访问,就近原则" << endl;
	Man  man;
	man.print1();
	man.print2();
	Sister woman;
	woman.print1();
	woman.print2();
	cout << "指针访问,正常赋值" << endl;
	Man* pm = new Man;
	pm->print1();
	pm->print2();
	Sister* pw = new Sister;
	pw->print1();
	pw->print2();
	cout << "指针非正常赋值:子类对象初始化父类指针" << endl;
	Man* parent = new Sister;
	//有virtual看对象类型,没有virutal看指针
	parent->print1();			//不是虚函数
	parent->print2();			//是虚函数  调用子类
	parent = new Man;
	parent->print2();		//调用父类			与51行同种行为 结果不同
}


//统一接口功能呢
void printInfo(Man* parent)
{
	parent->print2();
}

int main()
{
	testVirtual();
	printInfo(new Sister);

	return 0;
}

        2.3 多态应用

                降低因为变化而要修改代码
                采用增加代码方式满足新需求

#include <iostream>
using namespace std;

class Shape
{
public:
	virtual void Draw()
	{
		cout << "绘制过程" << endl;
	}
protected:
};
class Rect :public Shape
{
public:
	void Draw()
	{
		cout << "画矩形" << endl;
	}
protected:

};
class Circle :public Shape
{
public:
	void Draw()
	{
		cout << "画圆" << endl;
	}
protected:

};
class Triangle :public Shape
{
public:
	void Draw()
	{
		cout << "绘制三角形" << endl;
	}
};
class Ellipse :public Shape
{
public:
	void Draw()
	{
		cout << "绘制椭圆" << endl;
	}
};
//降低因为变化而要修改代码
//采用增加代码方式满足新需求
//统一接口
class Tool
{
public:
	void draw(Shape* parent)
	{
		parent->Draw();
	}
};
int main()
{

	Tool* pTool = new Tool;
	pTool->draw(new Circle);
	pTool->draw(new Rect);
	pTool->draw(new Triangle);
	pTool->draw(new Ellipse);


	return 0;
}

3 纯虚函数 

        纯虚函数也是虚函数,只是纯虚函数函数没有函数体

        3.1 写法

virtual void print()=0;

        3.2抽象类

        具备至少一个纯虚函数的类称为抽象类

                抽象类不可以构建对象

                抽象类可以构造对象指针

                所有子类重写函数必须和父类的一模一样

                子类想要创建对象必须重写父类的纯虚函数

                        可以增加别的函数和成员

        纯虚函数没有被重写,无论被继承多少次 都是纯虚函数

        虚函数无论被继承多少次都是 虚函数

4 虚析构

        在用子类对象初始化父类指针,为确保子类对象能被释放,父类的析构需要用virtual修饰

#include<iostream>
using namespace std;

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

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


int main()
{
	//子类对象初始化父类指针,父类需要虚析构做内存释放
	parent* pp = new son;
	delete pp;	//父类不是虚析构 这是子类无法释放内存;

	return 0;
}

5 两个关键字

       final      禁止重写 

                 放在 虚函数的后面

                子类继承后  不可重写函数,即使到孙子类内 也不可重写

        override        强制重写   标识作用

                用在子类中 重写父类函数,起到标识作用        如果父类中没有该函数,会报错

                用来检查父类中是否存在当前虚函数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值