2017-01-13 5 views
0

私はC++を学んでいます。 私の質問は、同じクラスであるが異なるデータをクラスに付ける方法に関連しています。これらのメンバーをテンプレートで呼び出すことができれば、コーディングを減らすことができます。それらを説明する。以下のコードをご覧ください。クラスのメンバーをC++でテンプレートで呼び出すことはできますか?

以下の2つのコードは、人物の種類とゲームの種類を示しています。

最初のものは、ItemHolderの継承によって実装されています。 Person_Inheritanceクラスは、テンプレートを通してBook.print()またはGame.print()を呼び出すことができます。したがって、呼び出すテンプレート関数は1つだけ必要です。このコードの削減は、ItemHolderの下でいくつかの関数を呼び出す必要がある場合にはるかに効果があります。

ただし、人物と書籍/ゲームには関係船があります。私は彼らが持っているときに構成を使うべきであることを学んだ。関係船。だから、私は構成によってコードを書き直す必要があった。

第1コードと同じことをするが、合成によって実装される第2コード。ポイントは、クラスがBook.print()またはGame.print()を呼び出すために2つの分離された関数を必要とすることです。 ItemHolderクラスの下でいくつかの関数を呼び出す必要があるとき、私はほとんどすべての関数を複数回書く必要があります。より多くのコーディングにつながります。私の質問の要約

(1)私はテンプレート関数でクラスのデータメンバを呼び出すことができますか?

(2)ルールを守る必要がありますか。つまり、関連船は継承を必要とし、関連船は組成を必要としていますか?

これは長い質問かもしれません。それらを読んでいただきありがとうございます。そして、あなたがあなたの解決策や提案を教えたら、私はもう一度あなたに感謝します。

基本クラス:継承によって

class Book { 
public: 
    Book() = default; 
    virtual ~Book() = default; 
    void print(void) { std::cout << "Bible" << std::endl; }; 
}; 

class Game { 
public: 
    Game() = default; 
    virtual ~Game() = default; 
    void print(void) { std::cout << "Pokemon" << std::endl; }; 
}; 

template <typename Item> 
class ItemHolder { 
public : 
    ItemHolder() = default; 
    virtual ~ItemHolder() = default; 
    void tellItem(void) { 
     item_.print(); 
    } 
private : 
    Item item_; 
}; 

実装:あなたの第二の例(組成物)において、組成物

class Person_Composition { 
public: 
    Person_Composition() = default; 
    virtual ~Person_Composition() = default; 

    void showBook() { book_.tellItem(); } 
    void showGame() { game_.tellItem(); } 

private : 
    ItemHolder<Book> book_; 
    ItemHolder<Game> game_; 
}; 

void test_1(void) { 
    Person_Composition Bill; 
    Bill.showBook(); 
    Bill.showGame(); 
} 
+0

データメンバーが呼び出し可能な場合は、それを呼び出すことができます。例えば、 'int'データメンバは呼び出し可能ではありません。 –

+0

なぜ両方ではないのですか? ['Person_Composition'が(ItemHolder'sの代わりに)単一の変数を持つ中間クラスに' Person_Inheritance'を入れてください。 'Person_Composition'は' showItem() 'をラッパー関数として提供することができます](http://ideone.com/BGLADG)。 –

+0

また、C++では、 'void f()'と 'void f(void)'はまったく同じです(具体的には、「非依存型の名前のない単一のパラメータで構成されるパラメータリスト ' void]は、空のパラメータリストと同等です。 "](https://timsong-cpp.github.io/cppwp/dcl.fct#4))、コードがCコードとしてコンパイルされている場合を除きます。この2つのうち、 'void f()'は純粋なC++コードのために_一般的に好まれていますが、これは意見の問題です。 –

答えて

3

によって

class Person_Inheritance : public ItemHolder<Book>, 
          public ItemHolder<Game> { 
public: 
    Person_Inheritance() = default; 
    virtual ~Person_Inheritance() = default; 
    template <typename T_Item> 
    void showItem() { 
     ItemHolder<T_Item>::tellItem(); 
    } 
}; 

void test_0(void) { 
    Person_Inheritance John; 
    John.showItem<Book>(); 
    John.showItem<Game>();  
} 

実装、それはあなたが言及することを避けられないのですbook_game_。そのクラスには、回避策はありません。

少なくとも2つの回避策があります。 C++にはprivateの継承がありますが、これはIS-Aの関係を意味しません。最初の例を再利用することができます。

第2に、構成を使用し、単一のstd::tuple<ItemHolder<Book>, ItemHolder<Game>>メンバーを持つことができます。

+0

お返事ありがとうございます、私は '私的な'継承を使用します。 – mora

関連する問題