我不是在谈论typeid,我只是在寻找将单个对象(例如,在我的情况下为std :: string)绑定到某个类的对象并使它的getter多态的某种通用方法。我真的不能给出正确的定义,所以我认为这就像获取类名的问题一样,但是您自己将其设置在某个地方,唯一的问题是在哪里设置它以及如何返回它。
我只是给出一些示例,这些示例可以满足我的要求,但实际上并没有达到我想要的效率。
virtual string GetClassName() const { return string("MyClass"); }
-每次调用字符串时都会花费额外的时间来构建和复制字符串const string& GetClassName() const { return class_name_; }
,其中class_name_
是在构造函数中设置的受保护的类字段-相同的字符串存储在每个对象中,因此内存效率不高我正在考虑将const引用返回到静态对象之类的方法,但是我真的找不到一种使它多态的方法。
有什么想法吗?
答案 0 :(得分:1)
只需使用合适的轮胎将其延长,就无需重新发明轮子。
C ++标准为您提供了typeid()
,它在所有情况下均适用,包括内置类型,自定义类,多态类,多重继承,虚拟继承等。
现在,您可能不喜欢typeid()
使用的特定于实现的名称。或者,您可能想使用自己的类型管理扩展来扩展可用的信息。在这种情况下,Bjarne Stroustrup在“ C ++的设计和演变”中提出了一种非常简单有效的解决方案。
typeid()
返回对const std::type_info
的引用。现在,您可以在unordered_map
中使用该对象的地址,将类型映射到您自己的自定义信息,以提供所需的名称。
此解决方案的优点:使用强大的内置功能,基于每个类一个附加的对象(可能是静态的),因此获得名称的开销非常低。您要做的就是考虑如何最好地填充地图。
这里有一个小而快速的概念证明(当然,必须加以改进):
// Basic principle of the idea
map<const type_info*, string> mytypes;
template <class T>
const string& mytype(T &&x) {
return mytypes[&typeid(x)];
}
// Some test types
struct A { virtual int test() {} };
struct B : A {};
int main() {
// To be improved: initialization of the type info extension
mytypes[&typeid(int)]="Plain C++ integer";
mytypes[&typeid(A)]="Structure A";
mytypes[&typeid(B)]="Structure B";
// demo, including polymorphic type
int a;
A * p = new B;
cout << typeid(int).name() <<endl;
cout << mytype(a) <<endl;
cout << mytype(*p) <<endl;
return 0;
}
答案 1 :(得分:0)
我想您想要的是带有NamedClass
的基础virtual std::string_view getName() const
,该基返回派生类的名称。因此,您需要类似typeid(object).name()
的名称,但没有名称修饰。
从NamedClass
派生的每个类都应覆盖getName
并返回类名。
class NamedClass {
public:
virtual std::string_view getName() const = 0;
};
class Derived final : public NamedClass {
public:
std::string_view getName() const override {
return "Derived";
}
};
如果您像我一样讨厌这种重复,则可以使用宏。
#define GET_NAME(NAME) \
std::string_view getName() const override { return #NAME; }
class Derived final : public NamedClass {
public:
GET_NAME(Derived)
};
如果您要做的只是“查看”字符串,我强烈建议使用std::string_view
而不是const std::string &
。