在C ++中,当我们使用typeid
获取对象或类的类型名称时,它将显示一个装饰(受损)字符串。我使用cxxabi
对其进行解算:
#include <cxxabi.h>
#include <typeinfo>
namespace MyNamespace {
class MyBaseClass
{
public:
const std::string name()
{
int status;
char *realname = abi::__cxa_demangle(typeid (*this).name(),0,0, &status);
std::string n = realname;
free(realname);
return n;
}
};
}
int main()
{
MyNamespace::MyBaseClass h;
std::cout << h.name() << std::endl;
}
gcc
中的输出是:
myNameSpace对象:: MyBaseClass
我需要从上面的字符串中删除MyNamespace::
。 我可以通过字符串操作删除它们 。
但有cxxabi
或其他库的标准方法可以做到这一点还是一个明确的解决方案?(至少可以在gcc和Visual C ++之间移植)
答案 0 :(得分:9)
没有标准的方法来执行此操作,因为没有标准的方法来进行名称修改。如何表示名称是故意未指定的。 C ++标准中没有ABI。您正在使用的函数abi::__cxa_demangle
是Itanium C ++ ABI的一部分。该功能在其他地方可能存在也可能不存在。
就使用Itanium C ++ ABI做你想做的事情而言,他们故意不提供这样的功能。
答案 1 :(得分:3)
我不知道这是否符合您的需求但我喜欢提及它。
您可以采取一些措施来获取您编写的类的名称。并且可以认为它在gcc和Visual C ++之间是可移植的。
在GCC中有一个名为 __ FUNCTION __ 的神奇变量作为gnu c language extensions的一部分,被视为变量 ,在C ++中。 (根据GCC版本,处理它的C不同。)
在Visual Studio中,有一个预定义宏,它具有相同的名称并执行相同的工作。说明是here。
使用 __ FUNCTION __ 获取当前函数的名称。因此,要获取类的名称,可以在类构造函数中使用它,如下所示:
namespace MyNamespace
{
class MyBaseClass
{
public:
MyBaseClass(): myName(__FUNCTION__){}
string name() { return myName; }
private:
string myName;
};
}
因此,如果您调用此类实例的"MyBaseClass"
函数,则会收到name()
响应。
答案 2 :(得分:2)
我针对此问题调查了cxxabi和其他c ++库,并且没有任何预定义的方法可以从中删除命名空间(至少在我的Google搜索中)。
我想知道你为什么不想操纵字符串?!
最佳解决方案和完全可移植(在gcc和vc ++中测试)简单如下:
<击> return n;
击>
return n.substr(n.find_last_of(':')+1);
当你从n
搜索lastColorPos
冒号并从lastColorPos
捕获字符串到结尾时,它是 definetly 类名。
答案 3 :(得分:1)
如果你只是想定义一个会返回类的字符串名的成员函数,而没有命名空间,那么我想知道为什么你甚至会使用cxxabi
甚至__FUNCTION__
或其他任何东西,除了简单地这样做:
namespace MyNamespace
{
class MyBaseClass
{
public:
//make the function const as well
std::string name() const { return "MyBaseClass"; }
};
}
我的意思是你可以完全控制类的实现,那么为什么只有一个 return-statement 就足够了呢?您也可以添加其他成员函数:
std::string fullname() const { return "MyNamespace::MyBaseClass"; }
看看这个有点相关的话题,也许你会得到更多提示:
答案 4 :(得分:0)
std::string removeNS( const std::string & source, const std::string & namespace_ )
{
std::string dst = source;
size_t position = source.find( namespace_ );
while ( position != std::string::npos )
{
dst.erase( position, namespace_.length() );
position = dst.find( namespace_, position + 1 );
}
return dst;
}
int main()
{
MyNamespace::MyBaseClass h;
std::cout << removeNS( h.name(), "MyNamespace::" ) << std::endl;
}