[C++]virtual关键字

清华郑莉C++
虚函数
若你打算允许别人通过基类指针调用对象的析构函数(通过delete)就需要让基类的析构函数称为虚函数
否则执行delete的结果是不确定的

/*8_5.cpp 虚析构函数 */
#include<iostream>
using namespace std;

class Base{
public:
	~Base();//不是虚函数 
}; 
Base::~Base(){
	cout<<"Base destructor"<<endl;
}
class Derived:public Base{
public:
	Derived();
	~Derived();//不是虚函数
private:
	int *p; 
};

Derived::Derived(){
	p = new int(0);
}
Derived::~Derived(){
	cout<<"Derived destructor"<<endl;
	delete p;
}
void fun(Base *b){
	delete b;	//静态绑定,只会调用~Base 
}

int main(){
	Base *b = new Derived();
	fun(b);//析构函数没有调用派生类中析构函数而是调用了基类中析构函数 
	return 0;
}
Base destructor

sd
针对8_5.cpp中;构函数没有调用派生类中析构函数而是调用了基类中析构函数
使用虚函数,使得派生类中与基类同名成员函数得到调用
虚函数表示意图
虚函数调用
虚函数指针vptr
虚函数表
纯虚函数:是一个在基类中声明的虚函数,它在该基类中没有定义
具体的操作内容,要求各派生类根据实际需要定义自己的版本,
声明格式:
virtual 函数类型(参数表) =0;
抽象类语法
带有纯虚函数的类称为抽象类:

class 类名{

virtual 类型 函数名(参数)=0;
其他类成员....
}

抽象类作用
将有关的数据和行为组织在一个继承层次结构中,保证派生类具有要求的行为。
对于暂时无法实现的函数,可声明为纯虚函数,留给派生类去实现
注意:抽象类只能作为基类使用、不定定义抽象类的对象

虚函数:
不设置为虚函数,派生类对象调用与基类同名成员函数,只能调用基类中成员函数
虚函数,有利于灵活地运行派生类及扩展多态形式

/*8_6.cpp 、 
*/
#include<iostream>
using namespace std;
//抽象类:带有纯虚函数的类称为抽象类 
//且抽象类只能作为基类使用,不能定义抽象类的对象 
class Base1{
public:
	virtual void display()const = 0;//纯虚函数 
//	void display()const = 0;//
}; 
void Base1::display() const{
	cout<<"Base1::display()"<<endl;
}
//派生类 
class Base2:public Base1{
public:
	virtual void display() const;//覆盖基类虚函数 
};

void Base2::display() const{
cout<<"Base2::display()"<<endl;
}

class Derived:public Base2{
public:
	virtual void display() const;//覆盖基类的虚函数 
};

void Derived::display() const{
	cout<<"Derived::display()"<<endl;
} 

//void fun(Base2 *ptr){  //结果一样。? 
void fun(Base1 *ptr){
	ptr->display();
}

int main(){
	//抽象类只能作为基类使用,不能定义抽象类的对象 
//	Base1 base1;//erro 
	
	Base2 base2;
	Derived derived;
//	fun(&base1);8
	
	fun(&base2);
	fun(&derived);
	return 0;
}
Base2::display()
Derived::display()

override
多态行为的基础:基类声明虚函数,派生类声明一个函数覆盖该虚函数
覆盖要求:函数签名(signature)完全一致
函数签名:函数名 参数列表 const

/*8_7.cpp*/ 
#include<iostream>
using namespace std;

class Base{
public:
	virtual void f1(int) const;
	virtual ~Base() {}
};

void Base::f1(int) const{
	cout<<"Base f1"<<endl;
}

class Derived:public Base{
public:
	void f1(int);
	~Derived(){
	}
};

void Derived::f1(int){
	cout<<"Derived f1"<<endl;	
}

int main(){
	Base *b;
	b = new Base;
	b->f1(1);//Base f1
	b = new Derived;
	b->f1(1);//Base f1  没有调用派生中成员函数,基类中成员函数为虚函数 
	return 0;
}
Base f1
Base f1

C++11引入显示函数覆盖,在编译期间而非运行时期间捕获此类错误;
在虚函数显示重载中运用,编译器会检查基类是否存在一虚函数,与派生类中带有声明override的虚函数,有相同函数签名(signature);若存在,则会回报错误 ;

/*8_7_1.cpp*/
struct Base1 final{
};
struct Derived :Base1{	//编译错误:Base1为final,不允许被继承 
};

struct Base2{
	virtual void f() final;
}; 

struct Derived2:Base2{
	void f();//编译错误:Base2::f 为final,不允许被覆盖 
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值