C++11の機能 (関数のdefault・delete宣言, overrideとfinal指定子, 移譲コンストラクタ, 継承コンストラクタ)

C++11の機能を紹介するシリーズ第四弾です。
今回は関数のdefault・delete宣言、overrideとfinal指定子、移譲コンストラクタと継承コンストラクタを紹介していきます。

関数のdefault・delete宣言

コンストラクタや代入演算子などにはユーザーが指定しなくても、必要に応じてコンパイラがそれらを自動的に作ってくれます。
ですが、「デフォルトで作ってほしくないんだよ」とか「コピーはしてほしくない」とか「この関数は呼べないようにしたい」という需要に答えるとなると、privateな部分に宣言だけ書いておくなど、あんまり綺麗でないやり方をするしかありませんでした。
そういうときに使うことができるのがdelete宣言です。delete宣言された関数は暗黙的に実体化されること無く、delete宣言された関数を必要とするコードが存在した場合コンパイルエラーになります。

対して、default宣言は、コンパイラが自動的に生成してくれるコードを明示的に生成させる宣言です。コピーやムーブで特殊な処理を行わない場合などはいちいち書くのは面倒で間違いの元になります。こういったときに使えます。また、virtualやinlineなどの指定子をつけた上でdefault宣言することもできるので、「仮想関数にするけど処理自体はコンパイラのデフォルトの動作で構わない」みたいな場合にも使えます。

struct Klass {
    Klass() = default; // デフォルトのコンストラクタはコンパイラのデフォルトで生成
    Klass(const Klass&) = delete; // コピーコンストラクタは削除
    Klass(Klass&&) = default;

    virtual ~Klass() = default; // 仮想関数としてデストラクタをデフォルト生成
};

overrideとfinal指定子

overrideはあのオーバーライドです。この指定子をつけることでこの関数はオーバーライドしているということを明示することができます。override指定子を付けているにもかからわずオーバーライドできていない場合はコンパイルエラーになります。なので、間違ってオーバーロードしてしまうバグの対策になります。
finalは継承の禁止とオーバーライドの禁止を明示することができる指定子です。
これら2つの指定子は文脈依存の予約語になるので普通の変数名や関数名に使用しても特に問題ありません。が、C++11以降であえて使うのは個人的にはあんまりおすすめしません。

struct Base {
    virtual void func() {}
    virtual void const_func() const {}
    virtual void final_func() {}
};

struct Derived final : Base {
    void func() override {}
    void const_func() const override {}
    void final_func() override final {}
};

移譲コンストラクタ

移譲コンストラクタは、あるコンストラクタから同じクラスの別のコンストラクタに処理を移譲することができる機能です。

struct Klass {
    Klass(int, int) {}
    Klass(int n) : Klass(n, n) {} // Klass(n, n)が移譲コンストラクタ
};

この例のように、メンバ初期化リストと同じように自身のコンストラクタを呼び出すことができます。

継承コンストラクタ

継承コンストラクタは基底クラスのコンストラクタを派生クラスで使えるようにできる糖衣構文です。

struct Base {
    Base(int) {}
};

struct Derived : Base {
    using Base::Base;
};

// 使う
Derived d(1); // Base(int)がDerived(int)として使えるようになっている。

コメント

このブログの人気の投稿

初めの挨拶

C++11の機能 (型推論, 範囲for)