在C ++中获得类名的一些好的技巧是什么?

时间:2019-02-21 06:20:23

标签: c++ types polymorphism typing classname

我不是在谈论typeid,我只是在寻找将单个对象(例如,在我的情况下为std :: string)绑定到某个类的对象并使它的getter多态的某种通用方法。我真的不能给出正确的定义,所以我认为这就像获取类名的问题一样,但是您自己将其设置在某个地方,唯一的问题是在哪里设置它以及如何返回它。

我只是给出一些示例,这些示例可以满足我的要求,但实际上并没有达到我想要的效率。

  • virtual string GetClassName() const { return string("MyClass"); }-每次调用字符串时都会花费额外的时间来构建和复制字符串
  • const string& GetClassName() const { return class_name_; },其中class_name_是在构造函数中设置的受保护的类字段-相同的字符串存储在每个对象中,因此内存效率不高

我正在考虑将const引用返回到静态对象之类的方法,但是我真的找不到一种使它多态的方法。

有什么想法吗?

2 个答案:

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

Online demo

答案 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 &