c++11 特性 final与override关键字

~~~~我的生活,我的点点滴滴!!


C++11中的final/override他们不是关键字,是说明符, 主要用在类继承间限定,虚函数重载的限定等

final 说明符

在通常情况下,一旦在基类A中的成员函数fun被声明为virtual的,那么对于其派生类B而言,fun总是能够被重载的(除非被重写了)。

有的时候我们并不想fun在B类型派生类中被重载,那么怎么办?C++98没有方法对此进行限制,但是c++11就对此作了限定,

那就是使用新的特性 final 说明符来约束,看下面代码:


C++11标准提供了说明符final,用于阻止派生类覆盖特定的虚方法或是阻止一个类成为基类:


//对类进行限定,不让其成为一个类的基类
1. class SomeClass final
{
   //.....
}

//对虚函数进行限定,不让其成子类重载去更改他的特性,因为有时候我们需要保留这样的特性

//又有人说,如果不想改变,那么直接把函数声明为非虚函数不就行了吗?

//其实 final 通常只在继承关系的“中途”终止某个派生类的重载。

//例如 A 派生 B 与 C

//B 在派生 D

//C 在派生 E

//假如在B这条分支上,想控制C使用B的某个方法(并且此方法肯定是从基类A重载来),

//那么可以在B中的这个虚函数后面加上final,这样C就不能在重载了,老老实实使用B的方法

//final只需要在声明时使用final进行修饰就可以了。实现时不需要带上,类似内联inline

2. class SomeClass
{
   type somefun(arg-list) final;
   //.....
}


代码:

#include<iostream>

class X
{
	private:
		char c;

	public:
		X():c('B'){}

		X(char arg):c(arg){}

		virtual void put()const final
		{
			std::cout << c << std::endl;
		}
	//final修饰了put()函数,使其不能被覆盖
	//...
};
 
class Y : public X
{
	private:
		int i;
	public:
		Y():i(0){}
		Y(int arg):i(arg){}
	//这里不能有void put();了,因为有了final说明符
	//...
};
 
class Z final//final修饰Z类,您不能从Z类派生出一个类,而只能用于创建对象
{
	private:
		double d;

	public:
		Z():d(0.0){}

		Z(double arg):d(arg){}

		void put()const
		{
			std::cout << d << std::endl;
		}
	//...
};
 
int main()
{
	char final='X';//可以这么做,因为final不是关键字,只是说明符,最好不要这样用。
	
	X x(final);

	x.put();//输出X

	Y y;
	y.put();//输出B

	Z z(3.14159);
	z.put();//输出3.14159

	return 0;
}

override说明符

C++11中为了帮助程序员写继承结构复杂的类型,引入了虚函数描述符override,如果派生类在虚函数声明时使用了override描述符,那么该函数必须是重载的其基类中的同名函数,否则代码将无法通过编译,这样能避免不小心覆盖基类的虚函数。

class B3
{
public:
    virtual void f() {}
};

class D3 : public B3
{
public:
    void f() {}
};

开发 D3 的程序员真的想重写B3::f函数吗?还是说,他只是不小心写了个与父类同名的函数,却在不经意间导致了覆盖?

为了避免这种错误,C++ 11 引入了override关键字(多么像 C# 啊!)。于是,我们会发现,下面的一段代码是会出错的:

class B4
{
public:
    virtual void g(int) {}
};

class D4 : public B4
{
public:
    virtual void g(int) override {} // OK
    virtual void g(double) override {} // Error
};

多亏了override关键字,我们可以让编译器帮我们检测到这个很难发现的程序错误。这段代码的错误在于,override关键字表明,g(double)虽然想要进行override的操作,但实际父类并没有这么个函数。

值得注意的是,这些并不是一些语法糖,而是能确确实实地避免很多程序错误,并且暗示编译器可以作出一些优化。

调用标记了final的virtual函数,例如上面的B2::f,GNU C++ 前端会识别出,这个函数不能被覆盖,

因此会将其从类的虚表中删除。而标记为final的类,例如上面的 B1,编译器则根本不会生成虚表。这样的代码显然更有效率。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值