コンパイル時にクラスが継承するものを変更するにはどうすればよいですか?

cREF

クロスプラットフォームのGUIフレームワークを作成するために、次の問題が発生しました。プロジェクトの一般的なプラットフォームに依存しないインクルードフォルダーに中央の「ウィンドウ」クラスがあるとします。

//include/window.hpp
class Window
{
    //Public interface
}

次に、次のようなプラットフォーム依存の実装クラスがいくつかあります。

//src/{platform}/window.hpp
class WinWindow {...}; //Windows
class OSXWindow {...}; //OSX
class X11Window {...}; //Unix

最後に、元のWindowクラスの.cppファイルがあります。ここで、実装クラスを一般クラスに「バインド」します。純粋に概念的には、これが私がやりたいことです。

//src/window.cpp
//Suppose we're on Windows

#include "include/window.hpp"
#include "src/win/window.hpp"
class Window : private WinWindow; //Redefine Window's inheritance

私はこれが決して有効なC ++ではないことを知っています、そしてそれがポイントです。私はこの問題を解決するために2つの可能な方法を考えました、そして私は両方に問題があります。

pImplスタイルの実装

Windowに実装クラスへのvoidポインターを保持させ、それをプラットフォームごとに異なるウィンドウクラスに割り当てます。ただし、プラットフォームに依存する操作を実行するたびにポインターをアップキャストする必要があります。もちろん、プラットフォームに依存するファイルをどこにでも含める必要があります。

プリプロセッサディレクティブ

class Window :
#ifdef WIN32
private WinWindow
#else ifdef X11
private X11Window //etc.

ただし、これは問題の実際の解決策というよりはハックのように聞こえます。

何をすべきか?デザインを完全に変更する必要がありますか?私の可能な解決策のいずれかが少し水を保持しますか?

ジャスティン

typedefを使用してプリプロセッサを非表示にする

代わりに、適切なウィンドウタイプをtypedefするだけで済みます。

#ifdef WINDOWS
    typedef WinWindow WindowType;
#elif defined // etc

次に、ウィンドウクラスは次のようになります。

class Window : private WindowType {
};

ただし、これはそれほど堅牢なソリューションではありません。よりオブジェクト指向の方法で考える方が良いですが、C ++でのオブジェクト指向プログラミングは、使用しない限り、実行時のコストがかかります。

不思議なことにテンプレートパターンを繰り返す

不思議なことに繰り返されるテンプレートパターンを使用できます

template<class WindowType>
class WindowBase {
public:
    void doSomething() {
        static_cast<WindowType *>(this)->doSomethingElse();
    }
};

その後、あなたはすることができます

class WinWindow : public WindowBase<WinWindow> {
public:
    void doSomethingElse() {
        // code
    }
};

そしてそれを使用するには(C ++ 14サポートを想定):

auto createWindow() {
#ifdef WINDOWS
    return WinWindow{};
#elif UNIX
    return X11Window{};
#endif
}

C ++ 11のみ:

auto createWindow()
    ->
#ifdef WINDOWS
    WinWindow
#elif defined UNIX
    X11Window
#endif
{
#ifdef WINDOWS
    return WinWindow{};
#elif defined UNIX
    return X11Window{};
#endif
}

使用するautoとき、またはtypedefと組み合わせて使用​​することをお勧めします。

auto window = createWindow();
window.doSomething();

オブジェクト指向スタイル

Windowクラスを抽象クラスにすることができます

class Window {
protected:
    void doSomething();
public:
    virtual void doSomethingElse() = 0;
};

次に、プラットフォームに依存するクラスをのサブクラスとして定義しますWindow次に、あなたがしなければならないのは、プリプロセッサディレクティブを1か所に置くことだけです。

std::unique_ptr<Window> createWindow() {
#ifdef WINDOWS
    return new WinWindow;
#elif defined OSX
    return new OSXWindow;
// etc
}

残念ながら、これには仮想関数の呼び出しによる実行時コストが発生します。CRTPバージョンは、実行時ではなくコンパイル時に「仮想関数」への呼び出しを解決します。

さらに、これWindowにはヒープ上で宣言する必要がありますが、CRTPでは宣言しません。これはユースケースによっては問題になるかもしれませんが、一般的にはそれほど重要ではありません。


最終的には、#ifdefどこかを使用する必要があるため、プラットフォームを決定できます(または、プラットフォームを決定するライブラリを使用できますが、おそらくそれ#ifdef使用します)。問題は、それをどこに隠すかです。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

コンパイル時に2つの基本クラスのうちの1つだけから継承するC ++クラスを作成するにはどうすればよいですか?

分類Dev

コンパイル時にクラスに継承された関数があるかどうかを確認するにはどうすればよいですか?

分類Dev

継承されたクラスの配列リストからアイテムを変更するにはどうすればよいですか?

分類Dev

SFINAEのstd :: enable_if_t&std :: is_base_ofを使用して、コンパイル時の継承を確認するにはどうすればよいですか?

分類Dev

サブクラスで継承されたAPIメンバーの名前を変更するにはどうすればよいですか?

分類Dev

コンパイル時にクラスがわからない場合、Enumの値を取得するにはどうすればよいですか?

分類Dev

C ++の継承されたクラスで通常のメソッドを静的メソッドに変更するにはどうすればよいですか?

分類Dev

Collection <>を継承するクラス内のコレクションにアクセスするにはどうすればよいですか?

分類Dev

プロパティ変更イベントを継承ラダーまで「追跡」するにはどうすればよいですか

分類Dev

パブリッククラスに継承されているときに、クラスがライブラリの外部に継承されないようにするにはどうすればよいですか?

分類Dev

継承を無視して、クラスが特定のタイプであるかどうかを確認するにはどうすればよいですか?

分類Dev

C ++で継承されたタイプのアクセスタイプを変更するにはどうすればよいですか?

分類Dev

実行時にコンボボックスのドロップダウンスタイルを変更するにはどうすればよいですか?

分類Dev

プライベートコンストラクターを持つクラスがこのクラスからの継承を妨げないのはなぜですか?特定のベースから継承できるクラスを制御するにはどうすればよいですか?

分類Dev

親クラスに C++ のデフォルト コンストラクターがない場合、継承されたクラスでコンストラクターを使用するにはどうすればよいですか?

分類Dev

継承可能なクラス変数を作成するにはどうすればよいですか?

分類Dev

親クラスのすべての機能を継承するにはどうすればよいですか?

分類Dev

Odooの純粋なPythonクラスから継承してメソッドを変更するにはどうすればよいですか?

分類Dev

Dでコンパイル時にクラス変数を設定するにはどうすればよいですか?

分類Dev

継承されたクラスが基本クラスのコンストラクターパラメーターを渡さなければならないことを回避するにはどうすればよいですか?

分類Dev

継承されたクラスが基本クラスのコンストラクターパラメーターを渡さなければならないことを回避するにはどうすればよいですか?

分類Dev

クラスのCSSスタイルを動的に変更するにはどうすればよいですか?

分類Dev

クラスにインターフェイスを実装し、別のクラスから継承させるにはどうすればよいですか?

分類Dev

継承するときに基本クラスのコピーを作成しないようにするにはどうすればよいですか?C ++

分類Dev

変数のコンパイル時型を取得するにはどうすればよいですか?

分類Dev

スパンをクリックして、スパンの色とテキストを継続的に変更するにはどうすればよいですか?

分類Dev

2つのクラスからUITextFieldを継承するにはどうすればよいですか?

分類Dev

クラスパスにクラスが存在する場合、暗黙のJavaコンパイルを防ぐにはどうすればよいですか?

分類Dev

Firefoxのインストールパスを変更するにはどうすればよいですか?

Related 関連記事

  1. 1

    コンパイル時に2つの基本クラスのうちの1つだけから継承するC ++クラスを作成するにはどうすればよいですか?

  2. 2

    コンパイル時にクラスに継承された関数があるかどうかを確認するにはどうすればよいですか?

  3. 3

    継承されたクラスの配列リストからアイテムを変更するにはどうすればよいですか?

  4. 4

    SFINAEのstd :: enable_if_t&std :: is_base_ofを使用して、コンパイル時の継承を確認するにはどうすればよいですか?

  5. 5

    サブクラスで継承されたAPIメンバーの名前を変更するにはどうすればよいですか?

  6. 6

    コンパイル時にクラスがわからない場合、Enumの値を取得するにはどうすればよいですか?

  7. 7

    C ++の継承されたクラスで通常のメソッドを静的メソッドに変更するにはどうすればよいですか?

  8. 8

    Collection <>を継承するクラス内のコレクションにアクセスするにはどうすればよいですか?

  9. 9

    プロパティ変更イベントを継承ラダーまで「追跡」するにはどうすればよいですか

  10. 10

    パブリッククラスに継承されているときに、クラスがライブラリの外部に継承されないようにするにはどうすればよいですか?

  11. 11

    継承を無視して、クラスが特定のタイプであるかどうかを確認するにはどうすればよいですか?

  12. 12

    C ++で継承されたタイプのアクセスタイプを変更するにはどうすればよいですか?

  13. 13

    実行時にコンボボックスのドロップダウンスタイルを変更するにはどうすればよいですか?

  14. 14

    プライベートコンストラクターを持つクラスがこのクラスからの継承を妨げないのはなぜですか?特定のベースから継承できるクラスを制御するにはどうすればよいですか?

  15. 15

    親クラスに C++ のデフォルト コンストラクターがない場合、継承されたクラスでコンストラクターを使用するにはどうすればよいですか?

  16. 16

    継承可能なクラス変数を作成するにはどうすればよいですか?

  17. 17

    親クラスのすべての機能を継承するにはどうすればよいですか?

  18. 18

    Odooの純粋なPythonクラスから継承してメソッドを変更するにはどうすればよいですか?

  19. 19

    Dでコンパイル時にクラス変数を設定するにはどうすればよいですか?

  20. 20

    継承されたクラスが基本クラスのコンストラクターパラメーターを渡さなければならないことを回避するにはどうすればよいですか?

  21. 21

    継承されたクラスが基本クラスのコンストラクターパラメーターを渡さなければならないことを回避するにはどうすればよいですか?

  22. 22

    クラスのCSSスタイルを動的に変更するにはどうすればよいですか?

  23. 23

    クラスにインターフェイスを実装し、別のクラスから継承させるにはどうすればよいですか?

  24. 24

    継承するときに基本クラスのコピーを作成しないようにするにはどうすればよいですか?C ++

  25. 25

    変数のコンパイル時型を取得するにはどうすればよいですか?

  26. 26

    スパンをクリックして、スパンの色とテキストを継続的に変更するにはどうすればよいですか?

  27. 27

    2つのクラスからUITextFieldを継承するにはどうすればよいですか?

  28. 28

    クラスパスにクラスが存在する場合、暗黙のJavaコンパイルを防ぐにはどうすればよいですか?

  29. 29

    Firefoxのインストールパスを変更するにはどうすればよいですか?

ホットタグ

アーカイブ