如何获取动态类型名称?
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
我该如何解决这个问题?
答案 0 :(得分:3)
声明你的函数返回typename为virtual
。否则,*this
仅会引用C
- O
子对象的部分。你也可以谷歌用于C ++中的多态性。
编辑。正如@“Cheers and hth。 - Alf”所指出的那样,将某些函数声明为virtual
就足以使类变为多态。并且声明析构函数virtual
是多态基类的必需品。但是你仍然需要将所有可能重新实现的函数声明为virtual
。
答案 1 :(得分:2)
让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();
}
答案 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)
代码中的一些错误:
其次,你不能使用
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;
}
请记住,类需要是多态的(即从具有虚函数的基类继承),以便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->
:您无法取消引用某个课程。免责声明:编译器没有触及代码(但是当你发布问题时,最好先把代码放到编译器中!)。