0

我有一组类都派生自一个公共基类。我想多态地使用这些类。该接口定义了一组 getter 方法,它们的返回值在给定的派生类中是恒定的,但从一个派生类到另一个派生类不同。例如:

enum AVal
{
  A_VAL_ONE,
  A_VAL_TWO,
  A_VAL_THREE
};

enum BVal
{
  B_VAL_ONE,
  B_VAL_TWO,
  B_VAL_THREE
};

class Base
{
  //...
  virtual AVal getAVal() const = 0;
  virtual BVal getBVal() const = 0;
  //...
};

class One : public Base
{
  //...
  AVal getAVal() const { return A_VAL_ONE };
  BVal getBVal() const { return B_VAL_ONE };
  //...
};

class Two : public Base
{
  //...
  AVal getAVal() const { return A_VAL_TWO };
  BVal getBVal() const { return B_VAL_TWO };
  //...
};

等等

这是一种常见的做事方式吗?如果性能是一个重要的考虑因素,我最好将属性拉到外部结构中,例如:

struct Vals
{
  AVal a_val;
  VBal b_val;
};

在每个实例中存储 a Vals*,并重写Base如下?

class Base
{
  //...
  public:
    AVal getAVal() const { return _vals->a_val; };
    BVal getBVal() const { return _vals->b_val; };
  //...
  private:
    Vals* _vals;
};

额外的取消引用本质上与 vtable 查找相同吗?这种情况的成语是什么?这两种解决方案都是愚蠢的吗非常感谢任何见解

4

4 回答 4

1

第一种方法看起来更清晰,并迫使您覆盖这些方法(无论如何在第一个孩子身上)。我认为虚拟通话的开销往往低于人们的预期。只有当您分析代码并且虚拟调用花费大量时间时,我才会尝试像您的第二种方法一样进行优化。

话虽如此,您要解决什么问题?有时像这样的类 id 很有用,但有时不同的接口抽象可以完成同样的事情,而根本不需要这样的接口。

于 2010-06-08T17:44:47.037 回答
1

我个人会实现一种 GetTypeStats(),它返回一个包含所有派生的特定信息的(引用)结构,或者像您在 D3D 中找到的 QueryInterface。在这种情况下,您还应该考虑静态多态性。但是,如果您的类必须是运行时多态的,那么您实际上无法做任何事情来消除虚函数调用。

于 2010-06-08T17:46:20.370 回答
0

如果所有不同的是值并且它们在编译时是固定的,则可以将它们设为模板参数:

template< AVal aval, BVal bval>
class Derived : public Base
{
  AVal getAVal() const { return aval };
  BVal getBVal() const { return bval };
};

typedef Derived<A_VAL_ONE, B_VAL_ONE> One;
typedef Derived<A_VAL_TWO, B_VAL_TWO> Two;
于 2010-06-08T18:20:04.190 回答
0

当程序员dynamic_cast想要避免使用dynamic_cast. 在这些情况下,这是一个微优化。与所有微优化一样,您需要根据需要使用合理的判断,然后再继续进行。如果分析器告诉您这样做没有性能提升,而不是dynamic_cast,您可能会更好地使用dynamic_cast.

于 2010-06-08T18:21:47.400 回答