Виртуальные методы C ++ для специфических для класса атрибутов или внешней структуры - PullRequest
0 голосов
/ 08 июня 2010

У меня есть набор классов, которые являются производными от общего базового класса.Я хочу использовать эти классы полиморфно.Интерфейс определяет набор методов-получателей, чьи возвращаемые значения постоянны для данного производного класса, но варьируются от одного производного класса к другому.Например:

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

, сохраняя Vals* в каждом случае и переписывая Base следующим образом?1011 *

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

Является ли дополнительная разыменование по существу такой же, как поиск в vtable?Какова установленная идиома для этого типа ситуации? оба этих решений тупые? Любые идеи очень ценятся

Ответы [ 4 ]

1 голос
/ 08 июня 2010

Лично я бы реализовал своего рода GetTypeStats (), который возвращает структуру (ссылку на), которая содержит всю производную конкретную информацию, или QueryInterface, как вы могли бы найти в D3D.Также следует учитывать статический полиморфизм в этом сценарии.Однако, если ваши классы ДОЛЖНЫ быть полиморфными во время выполнения, то вы ничего не можете сделать для устранения вызовов виртуальных функций.

1 голос
/ 08 июня 2010

Первый метод кажется более понятным и заставляет вас переопределить эти методы (во всяком случае, у первого потомка).Я думаю, что издержки виртуальных звонков, как правило, меньше, чем можно было бы ожидать.Только если вы профилируете код и виртуальные вызовы отнимут уйму времени, я попытаюсь выполнить оптимизацию, как при втором подходе.

При этом, какую проблему вы пытаетесь решить?Иногда такие идентификаторы классов полезны, но иногда другая абстракция интерфейса может выполнить то же самое, даже не имея такого интерфейса.

0 голосов
/ 08 июня 2010

Это обычный способ сделать «1001» для полиморфных типов для бедного человека, когда программист хочет избежать использования dynamic_cast.В этих случаях это микрооптимизация.Как и во всех микрооптимизациях, вам нужно использовать здравые суждения, основанные на потребность , прежде чем идти дальше.Если профилировщик скажет вам, что при выполнении этой операции нет выигрыша в производительности, а не dynamic_cast, вам, вероятно, было бы гораздо лучше, если бы вы использовали dynamic_cast.

0 голосов
/ 08 июня 2010

Если все, что отличается, это значения, и они зафиксированы во время компиляции, вы можете сделать их аргументами шаблона:

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;
...