LoginSignup
2
1

More than 5 years have passed since last update.

NVIとautoキーワードの相性の悪さ

Last updated at Posted at 2014-12-07

さて、C++の深い話的なやつを書いてくつもりではあるのですが、さしあたり、「なんぞこれ...」 っていうの見つけたので書いておこうと思う。
解決策的なのとかがあれば誰かご教授ください。

autoキーワード

autoキーワードはC++11から導入されたインスタンス化される実態を元に型を決めるっていうやつです。型をそんなに意識しなくて良くなるのですが、僕はなんか好きになれないでいたんですわ。便利といえば便利だけど。

auto.cpp
#include <iostream>
using namespace std;
int main() {
    auto a = 10;
    cout << a <<endl; // -> 10
}

NVIパターン

NVIっていうイディオムがあります。書き方はつまりは Template methodの書き方と同じです。 公開インターフェース(public)な関数はvirtualつけるんじゃないよ。っていう意味です。何がいいかと一言で言うと、ダッグタイピングした際に継承先で挙動を変更させないで、基底クラスの公開インターフェースが使われるので、インターフェース部分の破壊が防がれるってことです。

NVI.cpp
#include <iostream>
using namespace std;

class Base {
private:
    //中身は未実装。これはカスタマイズポイント
    void a() = 0;
    void b() = 0;
public:
    //単にa()とb()を実行する関数。これはオーバーライドさせるつもりではない
    void c() {
        a();
        b();
    }
};

class Derived : public Base {
private:
    void a() {
        cout << "a" << endl;
    }
    void b() {
        cout << "b" << endl;
    }
    void c() {
       cout << "test derived" << endl;
    }
};

int main() {
    Base* base = new Derived();
    base->c(); // -> a \n b

    auto base = new Derived();
    base->c(); // -> test derived
}

なんということか... いや、そりゃそうだろって思うけど。
つまりは何が言いたいかっていうと実態にしか目を当てないautoってやり方と、クラスの継承関係を強く意識してコードを書くNVIのやり方がすごいちぐはぐになって見えるのは僕だけでしょうか。

つまりは、C++11移行だぜ!って言ってダッグタイピングしているところを全部autoで書き直していくと、継承先で名前がぶつかっていた場合 予期せぬ壊れ方をしそうな気がします。Base型で Derivedをインスタンス化した場合とかをよく意識して書いていたのにこれからautoばっかつかう感じになると不幸な時代が来るかもしれません。唯一の解決策としては、オーバーライドするつもりなら、 overrideキーワードを付けろってことになりますね...

override.cpp
#include <iostream>
using namespace std;

class Base {
private:
    //中身は未実装。これはカスタマイズポイント
    void a() = 0;
    void b() = 0;
public:
    //単にa()とb()を実行する関数。これはオーバーライドさせるつもりではない
    void c() {
        a();
        b();
    }
};

class Derived : public Base {
private:
    void a() {
        cout << "a" << endl;
    }
    void b() {
        cout << "b" << endl;
    }
    // Base::c()はvirtualじゃないのでコンパイルエラー!!!
    void c() override {
       cout << "test derived" << endl;
    }
};

int main() {
    Base* base = new Derived();
    base->c(); // -> a \n b

    auto base = new Derived();
    base->c(); // -> test derived
}

これでコンパイル時にバグをつぶせそうですが... overrideを強制する仕掛けはないんですかね。

2
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1