5

オブジェクトを引数として取得し、その型を出力する問題を考えてみましょう。

#include <iostream>

class A { };
class B : public A { };
class C : public A { };
class D : public C, public B { };

using namespace std;

template<class T>
void print_type(T* info)
{
    if(dynamic_cast<D*>(info))
        cout << "D" << endl;
    else if(dynamic_cast<C*> (info))
        cout << "C" << endl;
    else if(dynamic_cast<B*>(info))
        cout << "B" << endl;
    else if(dynamic_cast<A*> (info))
        cout << "A" << endl;
}

int main(int argc, char** argv)
{
    D d;
    print_type(&d);
    return 0;
}

「派生クラス「D」から基本クラスへのあいまいな変換」というエラーが発生します。
しかし、あいまいさがどこにあるのかわかりません。main(d)で宣言されたオブジェクトがタイプDの場合、タイプAに直接変換できないのはなぜですか。

また、もちろん文字列型の引数を渡すと、他のエラーが発生します。
'std::basic_string<char>' is not polymorphic

ジェネリックスのJavaには、次の構文があります<T extends A>。この場合、それは役に立ちます。テンプレートを使用してC++で同様のものを作成するにはどうすればよいですか?


私はこのようにコードを変更しました:

#include <iostream>
#include <vector>

class A { };
class B : virtual public A { };
class C : virtual public A { };
class D : public C, public B { };

using namespace std;

template<class T>
void print_type(T* info)
{
    if(dynamic_cast<D*>(info))
        cout << "D" << endl;
    else if(dynamic_cast<C*> (info))
        cout << "C" << endl;
    else if(dynamic_cast<B*>(info))
        cout << "B" << endl;
    else if(dynamic_cast<A*> (info))
        cout << "A" << endl;
}

int main(int argc, char** argv)
{
    string str;
    print_type(&str);
    return 0;
}

しかし、それでもエラーが発生します。'std::basic_string<char>' is not polymorphic

4

3 に答える 3

8

まず第一に、これはテンプレートの問題ではありません。テンプレートを削除して、を取得しただけのprint_type場合D*は、エラーが引き続き存在することがわかります。

何が起こっているのかというと、仮想継承を使用していないため、次のような状況になります。

A   A
|   | 
B   C
 \ /
  D

dynamic_castは、参照しているもの Aを認識していません。

これを達成するために:(そして私はそれがあなたが望んでいたものだと思います)

  A
 / \
B   C
 \ /
  D

...仮想継承を使用する必要があります、ergo:

class A
{
};

class B : virtual public A
{
};

class C : virtual public A
{
};

class D : public C,public B
{
};

...そして今では問題なくコンパイルされます:)(仮想継承は悪であることに注意してください)

于 2012-04-05T23:21:03.333 に答える
3

これは、死の致命的なダイヤモンド、または単にダイヤモンド問題と呼ばれます。Aへの「パス」はBまたはCのいずれかを通過できるため、矛盾が生じる可能性があります。

さらに、テンプレートのアイデアは、タイプを意識するのではなく、一般的なものにすることです。テンプレート自体はコンパイルされたコードではなく、その使用に対してコンパイルされます。大きなマクロによく似ています。

于 2012-04-05T23:19:43.747 に答える
0

オブジェクトを引数として取得し、そのタイプを出力する問題を考えてみましょう。

ため息...RTTIを使用します。

#include <iostream>
#include <string>
#include <typeinfo>

template<class T> void print_type(const T& info){
    std::cout << typeid(info).name() << std::endl;
}

int main(int argc, char** argv){
    D d;
    int a = 3;
    std::string test("test");
    print_type(d);
    print_type(a);
    print_type(test);
    return 0;
}
于 2012-04-05T23:41:32.423 に答える