一、重写函数要满足的条件
- 基类函数必须是virtual
- 函数名(除了析构函数);形参类型;常量性必须一致
- 返回值和异常类型与派生类必须兼容
- 在C++中,只要原来的返回类型是指向基类的指针或引用,新的返回类型是指向派生类的指针或引用。覆盖的方法就可以改变返回类型。这样的类型成为协变返回类型
- 引用 限定符必须一致(from C++11)
只要满足上面四点就是函数重载。但是如果你希望进行函数重载,由于疏忽某一条未满足,编译器是不会报错的,所以override可以视为是一种重载的保证。
二、final
向虚函数添加final可以防止派生类重写,final也能用于类,这个类不能用作基类
三、引用限定符
用于区分一个成员函数被哪个对象调用
#include <iostream>
#include <string>
#include <vector>
class Base
{
public:
virtual void mf1() const &
{
std::cout << "Base:: virtual mf1" << std::endl;
};
void mf2()
{
std::cout << "Base:: mf2" << std::endl;
}
virtual void mf3()
{
std::cout << "Base:: virtual mf3" << std::endl;
}
virtual void mf4() final
{
std::cout << "Base:: virtual mf4" << std::endl;
}
};
class Derived : public Base
{
public:
void mf1() const & override
{
std::cout << "Derived:: virtual mf1" << std::endl;
};
void mf2()
{
std::cout << "Derived:: mf2" << std::endl;
}
void mf3() override
{
std::cout << "Derived:: virtual mf3" << std::endl;
}
// void mf4() override
// {
// std::cout << "Derived:: virtual mf4" << std::endl;
// }
};
class Widget
{
public:
using DataType = std::vector<double>;
DataType &data() & // 对于左值Widgets,
{
return values;
} // 返回左值
DataType data() && // 对于右值Widgets,
{
return std::move(values);
} // 返回右值
private:
DataType values;
};
Widget makeWidget()
{
return Widget();
}
int main()
{
// Base b1;
// b1.mf1();
// b1.mf2();
Derived d1;
// d1.mf1();
// d1.mf2();
Base *b2 = &d1;
b2->mf1();
b2->mf2();
b2->mf3();
Widget w;
auto vals1 = w.data(); // 拷贝w.values到vals1
auto vals2 = makeWidget().data();
}