c ++存储对象的类型,更好的选择是什么?

时间:2014-07-03 19:39:24

标签: c++

没有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;}
};

一般来说什么是更好的选择,它们的利弊是什么?

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

您不需要直接基类的虚拟继承,也不需要任何基类成员变量来支持此功能

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();

查看工作示例here

注意:
您在此类系统的当前配置中使用的所有类型都需要在编译时熟知。这并不支持Plugin pattern based机制。

答案 2 :(得分:0)

好的,我会刺伤......

  

“他们的利弊是什么?”

您的第一个示例virtual int getType() const =0;会产生额外的处理开销。对于CPU来说,virtual函数调用可能更难以抢占。 This issue may be trivial

您的第二个示例inline int getType() const { return id_; }会产生额外的运行时存储空间。并且为每个int的每个实例存储额外的Base。这也可能是微不足道的。

  

“一般来说什么是更好的选择?”

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