私はこれが畳み込まれているようですが、誰かが私の間違いを指摘してくれることを願っています。デザインがあなたの口の中に悪い味を残すと確信しています。私はデザインの選択肢を聞いてうれしいです。しかし、この形式は、問題領域のモデリングに由来します。テンプレート引数を解決できないために多型に失敗しましたか?
私はばかげていると確信していますが、テンプレートが継承して私を混乱させる方法については何かがあります。ここではいくつかは、以下の説明でコードをダウン切り詰めです:
// main.cpp
#include <cstdio>
template <typename POD>
class A {
public:
POD data;
POD get_a() { return data; }
};
template <typename T>
class B {
public:
virtual void do_something_with_an_A_child(const T&) = 0;
};
class ADerived : public A<float> {
public:
ADerived(float a) { data = a; }
};
class BDerived : public B<ADerived> {
public:
virtual void do_something_with_an_A_child(const ADerived& someA) {
printf("A bit of A-type's data: %f\n", someA.data);
}
};
template <typename POD>
class Aggregator {
public:
A<POD>* instanceOfA;
B<A<POD>>* instanceOfB;
Aggregator(A<POD>* anA, B<A<POD>>* aB) : instanceOfA(anA), instanceOfB(aB) {}
};
int main() {
ADerived myADerived(3.14159f);
BDerived myBDerived;
Aggregator<float> myAggregator(&myADerived, &myBDerived);
return 1;
}
のでA
署名ほんの一部がビルトインされるタイプ(複数可)のクラステンプレートです。 (私の特別なケースでは、A
にはその内部データを操作するメソッドがあります)。クラスB
は、A<.>
の特定のインスタンスを対象としたいくつかの操作に対するインタフェースを約束します。上のコードでは、A
とB
をテンプレートクラスとして定義し、これらのテンプレートクラスを継承するクラスを作成して、ADerived
とBDerived
としています。
(真の場合、A
は、数学的モデルといくつかのデータを表し、そしてB
モデルに数学的な最適化を行うためのインタフェースである。)次に
のインスタンスへのリンクを有していなければならないクラスをADerivded
とBDerived
(それらのインターフェイスに基づいて一般的なアルゴリズムを作成する目的で)私はAggregator
を呼び出しました。これは単にコンストラクタでいくつかのポインタが必要です。 は、POD
タイプについて知りたいだけです。これは、インターフェイスを操作するだけであり、オブジェクトに含まれるものについてあまり心配する必要がないからです。
私は-std=c++14
とclang++
から次のコンパイラエラーを取得する:
main.cpp:42:21: error: no matching constructor for initialization of 'Aggregator<float>'
Aggregator<float> myAggregator(&myADerived, &myBDerived);
^ ~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:35:3: note: candidate constructor not viable: no known conversion from 'BDerived *' to 'B<A<float> > *' for 2nd argument
Aggregator(A<POD>* anA, B<A<POD>>* aB) : instanceOfA(anA), instanceOfB(aB) {}
^
意味が明確であるが、私はそれがBDerived
がB<A<float>>
であることを見ることができない理由はわかりません。つまり、具体的にはB<ADerived>
ですが、ADerived
はA<float>
であるため、BDerived
はB<A<float>>
と見なされます。これは明らかにそうではありませんので、私は何かばかげたことをしています。誰かにそれを指摘させてもらうか、これはC++では不可能です。代替設計提案が必要です。
'B'と 'B >' ADerived'が 'か'から継承された場合に完全に異なるタイプが、それは問題ではないです。あなたのデザインは正しく見えませんが、何かを提案することは難しく、十分な情報がありません。 –
Slava
提案、テンプレートなしで特定のタイプに必要なものを実装して一般化することは非常に簡単です。 – Slava
ありがとう@Slava。それを信じるかどうか、これは既に特定のタイプのためにコーディングしたアルゴリズムから_lift_しようとする試みです。私はライブラリ/フレームワークに私のAPIを一般化しようとしています。それは正しいことが難しく、私はそうではないと確信しています。しかし、私たちはみな何とか学びます。 – Timtro