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使用 a D*,您会看到错误仍然存​​在。

发生的事情是您使用虚拟继承,因此您会遇到这种情况:

A   A
|   | 
B   C
 \ /
  D

dynamic_cast 不知道您指的是哪个。 A

为了实现这一点:(我认为这是你想要的)

  A
 / \
B   C
 \ /
  D

...您应该使用虚拟继承,因此:

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 回答