ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

条款12.为意在改写的函数添加override声明

2021-05-15 12:29:27  阅读:164  来源: 互联网

标签:Widget 12 函数 void 左值 改写 override doWork


为意在改写的函数添加override声明

class Base{
public:
    virtual void doWork();		//基类中的虚函数
};

class Derived : public Base{
public:
    virtual void doWork();		//改写了Base::dowork
};

std::unique_ptr<Base> upb = std::make_unique<Derived>();	//创建基类指针,指向派生类对象

upb->doWork();			//通过基类指针调用doWork
						//结果是派生类函数被调用

如果要改写动作真的发生,以下要求必须满足

  • 基类中的函数必须是虚函数
  • 基类和派生类中的函数名字必须完全相同(析构函数例外)
  • 基类和派生类中的函数形参类型必须完全相同
  • 基类和派生类中的函数返回值和异常规格必须兼容
  • 基类和派生类中的函数引用饰词必须完全相同
    • 函数引用饰词是为了限制成员函数仅用于左值或右值,带有引用饰词的成员函数,不必是虚函数
class Widget{
public:
    void doWork() &;		//这个版本的doWork仅在*this是左值时调用
    
    void doWork() &&;		//这个版本的doWork仅在*this是右值时调用
};

Widget makeWidget();		//工厂函数

Widget w;				//普通对象(左值)

w.doWork();				//以左值调用Widget::doWork
						//即Widget::doWork &

makeWidget().doWork();	//以右值调用Widget::doWork
						//即Widget::doWork &&

如果基类中的虚函数带有引用饰词,则派生类要对该函数进行改写,必须也带有完全相同的引用饰词。如果不然,那么这些声明了的函数在派生类中依然存在,只是它们不会改写基类中的任何函数

C++11提供了一种方法来显式地标明派生类中的函数是为了改写基类版本,为其加上override声明

class Base{
public:
    virtual void mf1() const;
    virtual void mf2(int x);
    virtual void mf3() &;
    virtual void mf4() const;
};

class Derived : public Base{
public:
    virtual void mf1() const override;
    virtual void mf2(int x) override;
    virtual void mf3() & override;
    virtual void mf4() const override;
};

C++11中的两个语境关键字finaloverride,它们的特色是,语言保留这两个关键字,但仅在特定语境下保留。对于override的情况下,它仅出现在成员函数声明的末尾时才有保留意义。这就意味着,如果你有一些遗留代码,其中已经用过override这个名字的话,你不必为了升级到C++11而改名。

如果我们想撰写一个函数,仅接受传入左值实参,则会声明一个非const左值引用形参:

void doSomething(Widget& w);		//仅接受左值的Widget类型

如果我们想撰写一个函数,仅接受传入右值实参,

void doSomething(Widget&& w);		//仅接受右值的Widget类型

成员函数引用饰词的作用就是针对发起成员函数调用的对象,即*this,加一些区分度。这和成员函数声明末尾加一个const的情形一摸一样:后者表明发起成员函数调用的对象,即*this,应该是const

class Widget{
public:
    using DataType = std::vector<double>;
    
    DataType& data() &			//对于左值类型,返回左值
    { return values; }
    
    DataType data() &&
    { return std::move(values); } 	//对于右值Widget类型,返回右值

private:
    DataType values;
};

左值引用类型的重载版本,返回的是左值引用(即一个左值);而右值引用类型的重载版本,则返回的是一个临时对象(即一个右值)。

//创建Widget类型对象的工厂函数
Widget makeWidget();

Widget w;

auto vals1 = w.data();		//调用Widget::data的左值重载版本
							//vals1采用复制构造完成初始化

auto vals2 = makeWidget().data();	//调用Widget::data的右值重载版本
									//vals2采用移动构造函数完成初始化

要点速记

  • 为意在改写的而函数添加override声明
  • 成员函数引用饰词使得对于左值和右值对象的处理能够区分开

标签:Widget,12,函数,void,左值,改写,override,doWork
来源: https://blog.csdn.net/qq_36553387/article/details/116842695

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有