在C ++中删除类型名称的名称空间

时间:2011-10-08 08:01:37

标签: c++ rtti

在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 ++之间移植)

5 个答案:

答案 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;
}