如何在C ++中获取动态类型名称?

时间:2014-01-11 10:24:21

标签: c++ oop

如何获取动态类型名称?

class O {
public:
std::string typename(){ return typeid(*this).name(); }
}

class C  : public O { /* ... */ }

O* varb = new C();
cout << O->typename(); // <--- return class O instead of class C

我该如何解决这个问题?

5 个答案:

答案 0 :(得分:3)

声明你的函数返回typename为virtual。否则,*this仅会引用C - O子对象的部分。你也可以谷歌用于C ++中的多态性。

编辑。正如@“Cheers and hth。 - Alf”所指出的那样,将某些函数声明为virtual就足以使类变为多态。并且声明析构函数virtual是多态基类的必需品。但是你仍然需要将所有可能重新实现的函数声明为virtual

答案 1 :(得分:2)

typename是C ++中保留的keyword

O::type_name() virtual通过C::type_name启用O*

#include <iostream>
#include <memory>

class O {
public:
    virtual std::string type_name() { return typeid(*this).name(); }
    virtual ~O() {}
};

class C: public O {};

int main() {
    std::unique_ptr<O> varb { new C() };
    std::cout << varb->type_name();
}

See it run!

答案 2 :(得分:1)

在我的Linux / Debian / Sid / x86-64系统上的文件

// file raffa.cc
#include <iostream>
#include <fstream>
#include <typeinfo>
#include <string>

class O {
public:
    virtual std::string type_name() {
        return typeid(*this).name();
    }
    virtual ~O() {};
};

class C  : public O {
    int f;
public:
    C(int k) : O(), f(k) {};
    virtual ~C() {};
    /* ... */
};

using namespace std;

int main() {
    O* varb = new C(__LINE__);
    cout << varb->type_name() << endl; 
    delete varb;
    return 0;
}   

编译
g++-4.8 -std=c++11 -Wall -O raffa.cc -o raffa
运行./raffa时显示

1C

前缀1可能是因为name mangling。请仔细查看 this question的答案以解开它。

PS:在现实生活中避免使用原始指针并且害怕memory leaks,所以不要在不理解这些问题的情况下逐字复制我的代码!使用valgrind ...

答案 3 :(得分:1)

代码中的一些错误:

  • 首先,您不能将 typename 用作自定义名称,它是C ++关键字。
  • 其次,你不能使用

    O* varb = new C(); 
    cout << O->typename();
    

    因为你试图取消引用一个类名,这没有任何意义。无论如何,你可能意味着 varb-&gt; typename()

对于typeid用法..如果你试图使用typeid动态返回指针引用的类的名称(运行时),你应该使用像

这样的东西
#include <iostream>
#include <typeinfo>
using namespace std;

class O {
public:
    virtual void vfunction() // Just one virtual function in the base to make the derived polymorphic
    {
        cout << "hello";
    }
};

class C  : public O 
{
    public:
    C() {};
};



int main() 
{
    // your code goes here

    O* varb = new C(); // Declare an O* pointer to C

    cout << typeid(*varb).name(); // This will print out "C", runtime info

    cout << typeid(varb).name(); // This will print out "O*"

    return 0;
}

http://ideone.com/K2RGd5

请记住,类需要是多态的(即从具有虚函数的基类继承),以便typeid返回解除引用时指向的运行时类指针。

此处提供更多信息:https://stackoverflow.com/a/11484105/1938163


注意:在上面的代码中,如果您使用的是gcc,您可能会看到与您使用的原始类型不同的类名...由于name mangling而由gcc自定义,如果您需要要显示的实际代码名称应该使用类似

的内容
#include <iostream>
#include <typeinfo>
#include <cxxabi.h> // Needed to demangle in gcc
using namespace std;

class O {
public:
    virtual void vfunction()
    {
        cout << "hello";
    }
};

class C  : public O 
{
    public:
    C() {};
};



int main() {
    // your code goes here

    O* varb = new C();

    int status;
    // Demangle symbols
    cout << __cxxabiv1::__cxa_demangle( typeid(*varb).name(), nullptr, 0, &status ); << endl;
    cout << __cxxabiv1::__cxa_demangle( typeid(varb).name(), nullptr, 0, &status );

    return 0;
}

答案 4 :(得分:1)

您无法以便携方式获取友好的人类可读类型名称,而无需自行指定每个类型名称。

然而,使用Visual C ++,typeid::name名称是人类可读的,并且使用g ++它们并不是太糟糕。

所以,只需更改当前代码

即可
class O {
public:
std::string typename(){ return typeid(*this).name(); }
}

class C  : public O { /* ... */ }

O* varb = new C();
cout << O->typename(); // <--- return class O instead of class C

class O {
public:
    std::string type_name() const { return typeid(*this).name(); }
    virtual ~O() {}
};

class C  : public O { /* ... */ };

O* varb = new C();
cout << varb->type_name(); // <--- return class O instead of class C

,其中

  • 函数名typename(即C ++关键字)已更改为type_name
  • 该函数已成为const,因此可以在const对象上调用它。
  • 添加了一个虚拟析构函数,使类多态typeid要求以多态方式工作)。
  • 在两个类定义的末尾添加了分号。
  • O->已更改为varb->:您无法取消引用某个课程。

免责声明:编译器没有触及代码(但是当你发布问题时,最好先把代码放到编译器中!)。