跳转至

类的新功能

默认成员函数

defaultdelete

C++11 提供了 defaultdelete 两个关键字,default 用来强制编译器生成一些默认成员函数,delete 是禁止编译器生成一些成员函数,给几个例子马上就可也理解:

class A
{
public:
    // 提供有参构造,要求编译器生成默认构造
    A() = default;
    A(int,int){}

    // 提供拷贝构造,要求编译器生成默认移动构造
    A(const A&) {}
    A(A&&) = default;

    // 禁止编译器生成拷贝赋值
    A& operator=(const A&) = delete;
};

要注意的是 default 只能用于默认成员函数,而 delete 可以用于任何函数,delete 更可能的用法是禁止特定的隐式类型转换:

void f(int){}
int main()
{
    f(1.1);
    return 0;
}
这里如果我们想禁止从 doubleint 的隐式类型转换,导致错误的函数调用,就可以使用 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)
*/
但是继承的基类构造函数只能对基类成员进行初始化,当我们同时想对派生类进行初始化时,就要使用初始化列表:

    B(int a,double b,char c): A(a,b),_c(c) {}

需要注意的是基类中编译器默认生成的构造函数是不会被继承的。

新增默认函数

原 C++ 类中有四个默认成员函数:默认构造,拷贝构造,拷贝赋值,析构函数。C++11 新增 移动构造移动拷贝 两个默认成员函数。会在 右值引用和移动语义 详细介绍。