对象的存储类型,选择什么更好

c++ Storing type of the object, what choice is better?

本文关键字:选择 什么 更好 类型 存储 对象      更新时间:2023-10-16

不使用RTTI,使用虚函数

我遇到了两种不同的常见解决方案来提供对象的类型:

使用虚方法调用并在方法中保留id:

class Base {
 public:
 virtual ~Base();
 virtual int getType() const =0;
};
class Derived : public Base {
 public:
 virtual int getType() const { return DerivedID; }
};

与内联方法调用和保持id在基类:

class Base {
 int id_;
 public:
 virtual ~Base();
 inline int getType() const { return id_; }
};
class Derived : public Base {
 public:
  Derived() { id_=DerivedID;}
};

一般来说什么是更好的选择,它们的优缺点是什么?

如果您在每个派生类中都选择第二个带有ID的选项,那么您将在创建的每个对象中都有一个额外的成员。如果使用虚函数的第一个选项,虚函数表中将有一个额外的指针,该指针只存在于每个类中,而不是每个对象中。如果类将有多个虚函数,那么第一个选项显然更好。即使不是,我也认为它更符合人们的期望。

根本不需要直接基类或任何基类成员变量的虚拟继承来支持此特性

struct Interface {
    virtual void foo() = 0;
    virtual int bar() = 0;
};
template<class T>
class Base : public Interface {
public:
    int getType() const { return getTypeId(); }
    static int getTypeId() { return T::ClassId; }
};
class Derived : public Base<Derived> {
public:
   static const int ClassId = DerivedID;
   virtual void foo() { }
   virtual int bar() { return 1; }
};

用法类似

Derived der;
Interface* iface = &der;
iface->foo();
iface->bar();

查看这里的工作示例。

注意:
这种系统的当前配置中使用的所有类型都需要在编译时众所周知。这并不支持基于插件模式的机制。

好的,我将尝试…

"它们的优缺点是什么?"

您的第一个示例virtual int getType() const =0;引起额外的处理开销virtual函数调用对于CPU来说更难以抢占。这个问题可能是微不足道的。

第二个例子inline int getType() const { return id_; }导致额外的运行时存储。并且为每个Base的每个实例存储额外的int。这也可能是微不足道的。

"一般来说,什么是更好的选择?"

一般情况下,避免过早优化。选择基类中的纯虚函数,因为它的正确性由编译器和运行时强制执行。