C ++ полиморфный класс, виртуальная функция и приведение к производительности - PullRequest
0 голосов
/ 20 июля 2011

У меня есть следующие классы:

class State
{
  protected:
    Vec3D accel;
    Vec3D gyro;
    Vec3D gps;
    float reward;
  public:
    boost::ptr_vector<Action> actions;
    ...
    virtual bool isTerm();
}

class guState : public State
{  
    float gps_stand_thres;
    float gps_down_thres;
  public:
    guState(Agent &A,ACTION_MODE &m);
    bool isTerm();
};

Существуют другие классы, которые все наследуют от State. Их различия заключаются только в том, как они оценивают isTerm (), который зависит от поведения. Я бы не стал использовать виртуальные функции для переопределения функции isTerm, если бы не тот факт, что есть несколько других шаблонных классов, предназначенных для работы со всеми видами классов, производных от состояний. Одним из них является Политика:

template <class S>
class Policy
{ 
  protected:    
    float QValue;
    S *state;
    S *nextState;
  public:
    ...
    template <class P>
    void updateOptimal(boost::ptr_vector<P> &policies);
}

updateOptimal должен получить класс, производный от State (в зависимости от поведения), приведенный из State * ptr к тому типу S, который используется в данный момент, для поиска политик для этого состояния. Теперь, поскольку производные от государства классы полиморфны, я предположил, что это было правильно:

S *s = dynamic_cast<S *>(iter->getNextState());

где iter является итератором Actions, а каждое действие имеет указатель State *nextstate; action-> nextstate установлен в другой точке:

action->setNextState(dynamic_cast<State *>(state)); 

Я мог бы шаблонировать весь класс Action, чтобы избежать использования State *nextstate; и использования S *nextstate;, но это потребовало бы огромного количества изменений по всему проекту.

Читая учебник по кастингу на cplusplus.com , насколько я понимаю, лучше всего использовать dynamic_cast, потому что он выполняет проверку типа перед приведением вверх или вниз. Однако в следующем коде после приведения я ничего не делаю в приведенном выше состоянии, кроме как использую его для поиска:

P *temp_pol = var::findPolicy(policies,s);

где findPolicy:

template <class P, class S>
P* findPolicy(boost::ptr_vector<P> &policies,S *state);
  • Было бы нормально пропустить проверки безопасности и использовать статическое приведение? я попробовал, и он компилируется.
  • Было бы нормально вообще пропустить проверки и сделать reinterpret_cast? Я тоже попробовал, и он компилируется.
  • Какое наказание за выполнение dynamic_cast? Я знаю, что есть маленький накладные расходы, но разве это серьезно?
  • Есть ли способ перехода с State * ptr на S-type * ptr без использования полиморфный класс (избегая виртуальной функции и просто переопределить это)?

1 Ответ

4 голосов
/ 20 июля 2011

Разница между static_cast и dynamic_cast заключается в том, что недопустимое static_cast является неопределенным поведением, в то время как недопустимое dynamic_cast приводит к нулевому указателю или исключению bad_cast (если вы приводите ссылки). Наказанием за dynamic_cast является проверка типа во время выполнения и увеличение размера кода из-за RTTI.

Итак, если вы уверены, что актерский состав всегда в порядке, вы можете смело использовать static_cast. Использование reinterpret_cast не даст вам никакого улучшения производительности по сравнению с static_cast, поэтому его не следует использовать здесь.

...