Лучший способ инициализировать встроенную переменную stati c, возвращаемую виртуальной функцией производного класса - PullRequest
2 голосов
/ 24 апреля 2020

Первоначально я имел m_damage в качестве члена класса в базовом классе Projectile, назначил значение в списке инициализатора в каждом производном классе и имел одну функцию получения в базовом классе.

Но затем я понял, что я не требуется каждый экземпляр производных классов, содержащих копию m_damage, так как это было одинаковое значение для всех экземпляров каждого производного класса, поэтому мне нужно было сделать значение static и заставить каждый производный класс возвращать его в функции virtual переопределить.

После исследования в сети и здесь я считаю, что переменная inline static const - это путь к go. Но есть ли польза от того, чтобы он был членом класса или константой класса? или есть другой лучший способ сделать это? Я хочу, чтобы доступ к значению осуществлялся только через частную виртуальную функцию в Projectile.

projectile.h file

class Projectile
{
private:
    virtual int getDamage() const = 0;
}

rocket .h file

class Rocket : public Projectile
{
private:
// inline static const auto ROCKET_DAMAGE = 400;  <---- make it a class member?
    virtual int getDamage() const final override;
}

rocket. cpp файл

// inline static const auto ROCKET_DAMAGE = 400;  <---- make it a class constant?

int Rocket::getDamage() const
{
    return ROCKET_DAMAGE;
}

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

С точки зрения разработки API константа - это деталь реализации. Поэтому вы можете захотеть скрыть эту деталь реализации - то есть константу - за определением функции-члена в файле .cpp, как у вас уже есть.

В rocket.hpp:

class Rocket: public Projectile {
private:
    virtual int getDamage() const final override;
};

In rocket.cpp:

static constexpr auto ROCKET_DAMAGE = 400; // not exposed to client

int Rocket::getDamage() const {
    return ROCKET_DAMAGE;
}

Обратите внимание, что наличие константы ROCKET_DAMAGE в качестве элемента данных, как в примере ниже, предоставляет ее клиенту:

class Rocket: public Projectile {
private:
   inline static const auto ROCKET_DAMAGE = 400;
};

Константа может быть скомпилирована в код клиента. Это будет означать, что клиентский код необходимо будет перекомпилировать каждый раз, когда вы изменяете значение константы ROCKET_DAMAGE.

В отличие от этого, если константа ROCKET_DAMAGE не предоставляется клиенту через заголовочный файл поскольку он скрыт в файле .cpp (как и в предыдущем случае), изменение значения константы не может потребовать перекомпиляции клиентского кода.

1 голос
/ 24 апреля 2020

Это хороший вариант использования для переменных класса c. Если она является константой и имеет одинаковое значение для всех объектов класса, она будет просто тратить память, если она является членом данных. Я бы опередил go и также сделал бы его constexpr, чтобы он выделялся во время компиляции и был доступен для вычислений во время компиляции, если вам это нужно (при условии, что у вас есть компилятор с поддержкой C ++ 17):

constexpr static auto ROCKET_DAMAGE = 400;

Другой способ решения этой проблемы - не использовать переменную stati c, а вместо этого просто вернуть значение непосредственно из виртуальной функции:

int Rocket::getDamage() const
{
    return 400;
}

Использование stati * Переменная класса 1013 * немного облегчит изменение значения в будущем, если вам необходимо: проще просто изменить заголовочный файл напрямую, чем переходить по файлу реализации и находить правильное определение функции. отрицательно, однако, если файл заголовка #include -d в нескольких файлах, так как это потребует перекомпиляции всех исходных файлов с этим заголовком, что означает более длительное время компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...