介绍了一个鲜为人知的 C++11 新特性,针对一个类成员函数的
class Widget { public: ... void doWork() &; // 只有当 *this 是 lvalue 时才调用 void doWork() &&; // 只有当 *this 是 rvalue 时才调用 }; ... Widget makeWidget(); // 制造一个临时的 Widget // 调用 Widget w; // 默认构造函数创建 w.doWork(); // 调用第一个版本(lvalue) makeWidget().doWork(); // 调用第二个版本
对于 重写 和 重载 ,这两个极易混淆,或者说不是混淆而是十分容易不小心就写错了,的功能,在 C++98 之前我们只能选择相信程序员写下的代码是准确无误的。有几个判断 重写 的条件
virtual
const
属性必须相同 上述关系缺一不可。
class Base { public: virtual void mf1() const; virtual void mf2(int x); virtual void mf3() &; // C++11 virtual void mf4() const; }; // C++98 class Derived : public Base { public: virtual void mf1() const; virtual void mf2(unsigned int x); virtual void mf4() const; }; // C++11 class Derived : public Base { public: virtual void mf1() const override; virtual void mf2(unsigned int x) override; virtual void mf3() & override; virtual void mf4() const override; };
其中 Derived
类中的 重写 函数前面的 virtual
不是强制性要求。相比于 C++98 而言对了一个关键字 override
,其作用就是帮助我们在编译期检查到是否在重写的时候出了差错
C++98版本的 mf2
函数可以通过编译,但是 C++11 版本的 mf2
函数便无法通过编译,因为 override
告诉编译器这是一个 重写 函数,但是实际上我们的 mf2
并不符合要求。
override
的作用便在于让编译器替我们检查错误,并且在实现一个工程时,往往需要改变某个函数来修改原有的内容业务,这时候可以借助编译器的 错误提示 看看修改这个函数,会对整个工程造成多大的影响,以及是否值得如此做。 对于新的 引用限定词 的用法,大体上会用在判断 lvalue 和 rvalue 上,其目的是为了避免某些不必要的开销,而不是依赖 编译器优化 这种虚无飘渺的说法。
class Widget { public: using DataType = std::vector<double>; ... DataType& data() & { return values; } DataType data() && { return std::move(values); } ... private: DataType values; };
可以很明显的看出,两个版本的 data
函数,是为了适应不同情况下对于 values
的使用。