在我正在工作的项目中,我需要能够访问程序中每个实例的完整类名。我的方法是声明一个基类,所有类都将从该基类派生,并且该方法将返回一个方法,该方法将返回给定实例的类的名称,并正确地进行解码。这看起来如下:
class Base {
public:
std::string *getClassName() {
char *str = (char*) malloc(1024);
size_t size = 1024;
int status;
char *res = abi::__cxa_demangle( typeid(*this).name(), str, &size, &status );
return new std::string(res);
};
class A : public Base { /*...*/ };
class B : public A { /*...*/ };
// ... and so on
问题在于,当我从B类实例访问getClassName
时,它不返回Base::A::B
而只返回Base
,这是从{声明getClassName
的地方。
我找到的唯一解决方案是使getClassName
虚拟并强制每个类实现它。但这意味着重写总是相同的代码,这是我不想要的。你知道任何优雅的解决方案吗?
答案 0 :(得分:4)
您只需在Base类中定义虚拟析构函数:
#include <iostream>
#include <malloc.h>
#include <cxxabi.h>
using namespace std;
class Base {
public:
virtual ~Base() {}
std::string getClassName() {
char *str = (char*) malloc(1024);
size_t size = 1024;
int status;
char *res = abi::__cxa_demangle( typeid(*this).name(), str, &size, &status );
return std::string(res);
}
};
class A : public Base { /*...*/ };
class B : public A { /*...*/ };
int main()
{
A a;
B b;
cout << a.getClassName() << endl;
cout << b.getClassName() << endl;
}
输出:
./test
A
B
在这种情况下BTW最好让__cxa_demangle分配内存(不要忘记:: free()它因为这个示例代码有内存泄漏)
答案 1 :(得分:0)
使您的Base
类成为派生类的模板,并将派生类的this
指针传递给构造函数。类似的东西:
template <DerivedT> class Base {
DerivedT * self;
public:
Base(DerivedT * s) : self(s) {}
// ....
};
然后在typeid
而不是*self
上致电*this
。
您的派生类必须成为:
template <DerivedT> class A : public Base<DerivedT> { /*...*/ };
class B : public A<B> { /*...*/ };
沿着构造函数链向上传递this
。
答案 2 :(得分:0)
有一个在Class Base中受保护的变量,并在每个派生类中设置它的值,并在getClassName中返回相同的变量..
class Base{
protected:
std:string* _pstrClassName;
}
class A{
A():_pstrClassName("A"){
}
}