1

私がやりたいこと:できるだけ一般的なテンプレートとして定義された単純なストレージクラス。そして、このクラスから別のクラスを派生させることができます。これは、何でも受け入れ、変換しint(アルゴリズムはここでは関係ありません)、基礎となるクラスに格納します。

しかし、これは期待どおりには機能しません。私が書いた最小限のテストケースは次のとおりです。

template<typename T>
class A {
  public:
    void f(T& foo) { }
};

class B : public A<int> {
  public:
    template<typename T>
    void f(T& foo) { }
};

int main() {
  A<int>* ptr = new B;
  ptr->f("foo");
  delete ptr;
  return 0;
}

もちろん、これはうまくいきません:

pierre@raringbeast:~/Workspace/Test/src$ icpc -o Test Test.cpp 
Test.cpp(16): error: a reference of type "int &" (not const-qualified) cannot
be initialized with a value of type "const char [4]"
    ptr->f("foo");
           ^

compilation aborted for Test.cpp (code 2)

コンパイラに B クラスのメソッド定義を強制的に使用させる方法はありますか、それとも本当に悪い考えですか?

--

編集:継承を公開しました。

4

2 に答える 2

3

まず、@GermanDiago が指摘したように、プライベート継承を使用しているため、「基本クラスにアクセスできません」というエラーが発生します。Bpublicから派生するように変更しますA<int>

それでも、これで問題は解決しません。名前の検索は、静的型に基づいています。へのポインターがある場合、A<int>そのポインターを介してメンバーにアクセスすると、 のメンバーのみが参照されますA<int>

のメンバーBを表示するには、 type を介してアクセスする必要があります。B

int main() {
  B* ptr = new B;
  ptr->f("foo");
  delete ptr;
  return 0;
}

もちろん、私があなたの質問を正しく理解していれば、これはあなたが本当に望んでいることではありません。代わりにCuriously Recurring Template Patternを参照してください。

template <class T, class Derived>
class A {
  public:
    template <class U>
    void f(U& bar) {
      static_cast<Derived*>(this)->f(bar);
    }

    void f(T& foo) {

    }
};


class B : public A<int, B>
{
  public:
    template <class T>
    void f(T &foo) {
      //will be called from A's f(U&)
    }
};


int main() {
  A<int, B>* ptr = new B;
  ptr->f("foo");
  delete ptr;
  return 0;
}

実際の例

もちろん、これにはの型のB一部になるという欠点があります。Aコンパイル時間のままで、これを回避する方法はないと思います。

于 2013-10-09T09:54:59.210 に答える
1

パブリック継承を使用する必要があります。

class B : public A<int> {
    //...
}

C++ での is-a 関係は、パブリック継承によるものです。プライベート継承は、現在使用しているものです。

于 2013-10-09T09:44:46.163 に答える