为意在改写的函数添加override

重写override

重写:在派生类中的虚函数实现,会改写基类中对应虚函数的实现

重写的要求:

  1. 基类中的函数必须是虚函数

  2. 基类和派生类中的函数名字必须完全相同(析构函数例外)

  3. 基类和派生类中的函数形参型别必须完全相同

  4. 基类和派生类的函数常量性(constness)必须完全相同

  5. 基类和派生类中的函数返回值和异常规格必须兼容

  6. 基类和派生类中的函数引用修饰词必须完全相同。

上面提到的重写要求前5点是C++98的要求,第6点是C++11对于重写的要求。 成员函数引用修饰词包含左值引用、右值引用修饰词,带有左值引用修饰词的成员函数只有*this是左值时调用,带有右值引用修饰词的成员函数只有*this是右值时调用, 例如:

class Person
{
public:
	void DoWork() &;
	void DoWork() &&;
}

// 返回Person右值
Person CreatePerson();

Person objPerson;

// 以Person对象左值调用成员函数DoWork() &
objPerson.DoWork()
// 以Person对象右值调用成员函数DoWork() &&
CreatePerson().DoWork()

在子类中增加重写override关键字有助于编译器检测所有与重写相关的问题,而没有这个关键字时很容易造成隐藏,关于隐藏可以参考这篇文章, override只有出现在成员函数声明的结尾才有意义,这就意味着,如果有一些C++11之前的代码用过了override这个名字也不必为了升级到C++11而改名:

class Person
{
public:
	void override();
}

成员函数引用修饰词


示例:

class Combat
{
public:
	Combat()
	{

	}

	Combat(const Combat& obj)
	{
		cout << "Combat(const Combat& obj)" << endl;
	}

	Combat(Combat&& obj)
	{
		cout << "Combat(Combat&& obj)" << endl;
	}
};

class Person 
{
public:
	void DoWork() &;
	Combat& GetCombat()
	{
		return m_objCombat;
	}

public:
	Combat m_objCombat
}
Person CreatePerson()
{
	return Person();
}

有如下调用:

CreatePerson().DoWork() 我们在成员函数后面增加了左值引用修饰词,也就意味着只有左值才能调用,编译期发生错误

auto combat = CreatePerson().GetCombat()GetCombat成员函数后面没有任何引用修饰词,当按照这种方式调用时, 其实发生了从临时对象(右值)返回Combat对象的左值引用,并以此为参数调用Combat对象的拷贝构造函数, 而对于临时对象的拷贝更应该是移动拷贝操作而非左值拷贝,从而避免牺牲效率,对于上例的修改:

class Person
{
public:
	void DoWork() &;
	Combat& GetCombat() &
	{
		return m_objCombat;
	}

	Combat GetCombat() &&
	{
		return std::move(m_objCombat);
	}

public:
	Combat m_objCombat
}

最后


  1. 为意在重写的函数添加override声明

  2. 成员函数引用饰词使得对于左值和右值对象*this的处理能够区分开来