如何获取动态类型名称?
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
我该如何解决这个问题?
// 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
PS:在实际生活中,避免使用裸指针并警惕内存泄漏,因此请不要直接复制我的代码而不理解这些问题!使用valgrind ...
typename
作为成员名称,而你修复这个bug没有任何问题。也要修复内存泄漏! - undefinedtypename
是C++中的保留关键字!请将O::type_name()
设为虚函数,以便通过O*
调用C::type_name
:"#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();
}
type_name()
设为virtual
更明确,但你说得对,一个virtual
析构函数就足够了。 - undefined你的代码中存在一些错误:
其次,你不能使用
O* varb = new C();
cout << O->typename();
因为你试图取消引用一个类名,这没有意义。你可能想要的是varb->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在解引用指针时返回它所指向的运行时类。#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;
}
如果不指定每个类型名称,您无法以可移植的方式获得漂亮易读的类型名称。
但是,在使用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->
:无法引用类。免责声明:代码未经编译器处理(但当您发布问题时,最好先将代码放入编译器中!)。
typename
是一个关键字。 - undefined