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

C++ 在C+;中获取类名的一些好技巧是什么+;?,c++,types,polymorphism,typing,classname,C++,Types,Polymorphism,Typing,Classname,我不是在谈论typeid,我只是在寻找将单个对象(例如,在我的例子中是std::string)绑定到某个类的对象并使其getter多态或其他的通用方法。我真的不能给出一个正确的定义,所以我认为这就像获取类名的问题一样,但是你自己在某个地方设置了它,唯一的问题是你在哪里设置它,以及如何返回它 我只想举几个例子,它们能做我想做的,但并没有我想要的那么有效 虚拟字符串GetClassName()const{return string(“MyClass”);}-每次调用字符串时都会花费额外的时间来构建

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

我只想举几个例子,它们能做我想做的,但并没有我想要的那么有效

  • 虚拟字符串GetClassName()const{return string(“MyClass”);}
    -每次调用字符串时都会花费额外的时间来构建和复制它
  • const-string&GetClassName()const{return class_-name}
    其中
    class_-name
    是在构造函数中设置的受保护类字段-每个对象中都存储相同的字符串,因此内存效率不高
我在考虑返回一个静态对象的常量引用,但是我真的找不到一种方法使它多态


有什么想法吗?

你不需要重新发明轮子,只要用合适的轮胎就可以了

C++标准为您提供了在所有情况下都能工作的工具,包括内置类型、自定义类、多态类、多重继承、虚拟继承等等

现在您可能不喜欢
typeid()
使用的名称,这些名称是特定于实现的。或者,您可能希望通过自己的类型管理扩展扩展扩展可用的信息。在这种情况下,Bjarne Stroustrup在《C++的设计与发展》中提出了一个非常简单有效的解决方案

typeid()
返回对
const std::type_info
的引用。现在,您可以在中使用此对象的地址,将类型映射到您自己的自定义信息,这些信息可以提供您想要的名称

此解决方案的优点:使用健壮的内置功能,基于每个类一个附加对象(可以是静态的),获得名称的开销非常低。您需要做的就是考虑如何最好地填充地图

这里是一个小型且快速的概念验证(当然必须改进):

//思想的基本原理
地图类型;
模板
常量字符串和mytype(T&&x){
返回mytypes[&typeid(x)];
}
//一些测试类型
结构A{virtual int test(){}};
结构B:A{};
int main(){
//有待改进:类型信息扩展的初始化
MyType [& Type ID(int)] =“普通C++整数”;
mytypes[&typeid(A)]=“结构A”;
mytypes[&typeid(B)]=“结构B”;
//演示,包括多态类型
INTA;
A*p=新的B;

cout我认为您需要的是一些基本的
NamedClass
,带有一个
虚拟std::string\u 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\u视图
而不是
const std::string&

您知道静态类属性吗?它们只存在一次,全局只初始化一次。
virtual const string&GetClassName()const{返回我的静态类名称;}
请将所显示的代码添加到完整的类示例中。这将使给出答案更容易。现在我想起来了,这是有意义的…我做对了吗?这些东西必须复制到我的每一个类中,并且没有办法避免代码重复?这是解决方案的缩影。任何类都必须提供这一点,至少,一个y非抽象。每个类都必须重载resp.virtual方法。因此,代码可能每次都是完全相同的。在我们的例子中,我们使用了方便宏(是的,宏:-())来实现这一点(防止键入错误)。但是,如果您忘记了一个类的这一点,它可能会从基类继承它,并在运行时返回错误的结果。我不知道有什么技术可以将这转化为编译时检查。另一个优点是:您可以在运行时检查类是否正确注册。(未注册的类可能会运行到
assert()中)
当询问其名称时。)有趣。共享基类的约束似乎很强。此外,在多重继承的情况下,这将如何工作?@Christophe在多重继承的情况下,您将实际上从
NamedClass继承,以避免致命的钻石。
#define GET_NAME(NAME) \
  std::string_view getName() const override { return #NAME; }

class Derived final : public NamedClass {
public:
  GET_NAME(Derived)
};