2016-04-11 3 views
1

Предположим, что следующие две версии одного и того же класса А:Что лучше: явный или безличный get()?

Version 1

class A 
{ 
    public: 
     enum class Retrievable { Integer, String }; 

     A(): m_integer(123), m_string("string") {} 
     ~A() {} 

     void* get(const Retrievable r) 
     { 
     switch (r) 
     { 
      case Retrievable::Integer: 
       return static_cast<void*>(&m_integer); 
      case Retrievable::String: 
       return static_cast<void*>(&m_string); 
      default: 
       throw; 
     } 
     } 

    private: 
     int m_integer; 
     std::string m_string; 
}; 

версия 2

class A 
{ 
    public: 
     A(): m_integer(123), m_string("string") {} 
     ~A() {} 

     int getInteger()  { return m_integer; } 
     std::string getString() { return m_string; } 

    private: 
     int m_integer; 
     std::string m_string; 
}; 

С точки зрения ясности, эффективности и расширяемости, какой из этих двух парадигм - единственная функция без функции get() или отдельная функция get() - лучше?

+0

Последний. В первом вам нужно указать как параметр 'r', так и тип возврата, который является подверженным ошибкам и излишним. Это также невозможно сделать «виртуальным». Первый полезен, когда вы каким-то образом используете указанный тип, например. для 'dynamic_cast', но в этом примере вы этого не делаете. – StenSoft

+0

Код, который не компилируется, быстрее, чем код, который делает. Версия 1 не компилируется, так что явная производительность. Чего ждать? Если вы хотите узнать, лучше ли вариант 1 или вариант 2, укажите * действующий рабочий код *, который описывает ваши варианты. Поскольку вышеизложенное не имеет никакого смысла - мне пришлось бы принципиально переписать один из ваших вариантов, чтобы он скомпилировался, и кто знает, переписал бы он тот же код таким же образом. – Yakk

+0

@Yakk Честно говоря, я еще не понял, в какой кодировке я могу скомпилировать рабочий образец. Однако я использовал второй метод по другим причинам. Это было теоретическое упражнение, мне было любопытно узнать ответ. Я уверен, что я могу собрать что-то подобное. Речь шла о теории, стоящей за ней, а не конкретно о том, что я опубликовал (я полагал, что это было по крайней мере частично неправильным). – Frostfyre

ответ

3

Вариант 1 отличает вещи от void* и выполняет диспетчеризацию времени, такое медленнее и менее безопасно и сложнее в использовании.

Запрет на взаимодействие с механизмом сценариев, я не могу представить причину использования опции 1. И даже тогда есть много способов справиться с этим. Интервьюируемый, который предложил вариант 1 как альтернативный вариант варианта 2, был бы сильным, не нанимать, и это заставило бы меня пересмотреть воронку, которая до сих пор получила интервьюируемого.

Короче говоря, вариант 2 лучше.

1

Вариант А не будет собирать в любом случае, потому что независимо от C вы будете пытаться вернуть тип, который не является C (указатель, где C является string и т.д.)

Version B, может быть, лучше, но и бросить криво. если вы не создаете какой-либо полиморфный тип, например узел JSON, или что-то еще, функция должна описывать поведение, а не тип возвращаемого значения.

:

еще раз, если вы не пишете какой-либо класс JSON, я не вижу большого смысла создавать функцию, которая описывает тип возвращаемого значения, а не поведение. Person не имеет getHand или getLeg функции, он имеет такие функции, как wave, walk и т.д.

Performace? Я сомневаюсь, что геттер будет зависеть от производительности вашего приложения.

+0

Это были просто общие названия для концепции.Так, например, getInteger() может быть getCurrentGameLevel() и возвращать m_currentGameLevel. – Frostfyre

+0

, так что в основном сравнение между 'get (Option :: GameLevel)' и 'getGameLevel'? без вопросов второй. поскольку он описывает поведение и определяется во время компиляции –