New Features for Classes
默认成员函数
default
和 delete
C++11 提供了 default
和 delete
两个关键字,default
用来强制编译器生成一些默认成员函数,delete
是禁止编译器生成一些成员函数,给几个例子马上就可也理解:
class A
{
public:
// 提供有参构造,要求编译器生成默认构造
A() = default;
A(int,int){}
// 提供拷贝构造,要求编译器生成默认移动构造
A(const A&) {}
A(A&&) = default;
// 禁止编译器生成拷贝赋值
A& operator=(const A&) = delete;
};
要注意的是 default
只能用于默认成员函数,而 delete
可以用于任何函数,delete
更可能的用法是禁止特定的隐式类型转换:
double
到 int
的隐式类型转换,导致错误的函数调用,就可以使用 delete
:
void f(int){}
void f(double) = delete;
int main()
{
f(1.1); // Compilation error : use of deleted function 'void f(double)'
return 0;
}
管理虚函数
final
final
修饰类时,被修饰类将不可以被继承。
class A final
{};
class B : public A
{};
/*
Compilation error:
cannot derive from 'final' base 'A' in derived type 'B'
*/
final
修饰虚函数时,该虚函数将无法在子类中被重写。
class A
{
public:
virtual void print() final { }
};
class B : public A
{
public:
virtual void print() { }
};
/*
Compilation error:
virtual function 'virtual void B::print()' overriding final function
*/
override
override
修饰虚函数,会强制要求子类重写被修饰的虚函数。
class A
{
public:
virtual void print() override {}
};
class B : public A
{};
/*
Compilation error:
'virtual void A::print()' marked 'override', but does not override
*/
委托构造函数
如果类中的某些构造函数需要使用其他构造函数中已有的代码,C++11 允许我们在构造函数的初始化列表中使用另一个构造函数,这被称作委托,因为该构造函数的一部分任务委托给了另一个构造函数:
class A
{
int _a;
double _b;
char _c;
public:
A(int a,double b):
_a(a),
_b(b)
{}
// 委托 A(int,double) 去初始化 _a , _b
// 此时 A(int,double,char) 是一个委托构造函数
// A(int,double) 是被委托函数
A(int a,double b,char c):
A(a,b)
{
_c = c;
}
};
对于委托构造函数需要注意几点:
- 被委托的构造函数在委托构造函数的初始化列表里被调用,而不是在委托构造函数的函数体里被调用。
class A
{
int _a;
double _b;
char _c;
public:
A(int a,double b):
_a(a),
_b(b)
{}
A(int a,double b,char c)
{
A(a,b); // 这样调用是无意义的,会被编译器忽略,不会执行构造。
_c = c;
}
};
- 委托构造函数的初始值列表中,只允许出现被委托的构造函数,而不能直接给成员变量进行初始化。
class A
{
int _a;
double _b;
char _c;
public:
A(int a,double b):
_a(a),
_b(b)
{}
A(int a,double b,char c):
A(a,b),
_c(c) // Compilation error:委托构造函数不能具有其他成员初始化表达式
{}
};
继承构造函数
C++11 允许派生类继承基类的构造函数,在面对基类必须初始化的情况下,不必在派生类中额外编写构造函数来对基类进行构造:
class A
{
int _a;
double _b;
public:
A(int a, double b) :
_a(a),
_b(b)
{
std::cout << "A(int a, double b)" << std::endl;
}
void f()
{}
};
class B : public A
{
char _c;
public:
using A::A; // 继承基类构造函数
};
int main()
{
B bb(1,1.1);
return 0;
}
/*
输出结果:
A(int a, double b)
*/
需要注意的是基类中编译器默认生成的构造函数是不会被继承的。
新增默认函数
原 C++ 类中有四个默认成员函数:默认构造,拷贝构造,拷贝赋值,析构函数。C++11 新增 移动构造 和 移动拷贝 两个默认成员函数。会在 右值引用和移动语义 详细介绍。