初始化派生 class 虚函数返回的内联静态变量的最佳方法

Best way to initialize inline static variable returned by derived class virtual function

最初我有 m_damage 作为基础 class Projectile 中的 class 成员,在每个派生的 class 中分配初始化列表中的值并且有一个getter 基函数 class.

但后来我意识到我不需要派生 class 的每个实例都持有 m_damage 的副本,因为它对于每个派生 class 的所有实例都是相同的值,所以我需要创建值 static 并在 virtual 函数覆盖中让每个派生 class return 它。

在网上和此处进行研究后,我相信 inline static const 变量是可行的方法。但是将它作为 class 成员或 class 常量有什么好处吗?或者还有其他更好的方法吗?我只想通过 Projectile 中的私有虚函数访问值。

projectile.h 文件

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

火箭.h文件

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

火箭 .cpp 文件

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

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

这是静态 class 变量的一个很好的用例。如果它是一个常量,并且对于 class 的所有对象都是相同的值,如果它是一个数据成员,它只会浪费内存。我会继续并使它 constexpr 所以它在编译时分配,并且可用于编译时计算,如果你需要它(假设你有一个启用 C++17 的编译器}:

constexpr static auto ROCKET_DAMAGE = 400;

解决这个问题的另一种方法是不使用静态变量,而是 return 直接从虚函数中获取值:

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

使用静态 class 变量将使将来更改值变得稍微容易一些,如果您需要:直接修改头文件比拖网实现文件更容易并找到正确的函数定义。但是,如果头文件在多个文件中是 #include-d,这可能是负面的,因为这将需要使用此头文件重新编译所有源文件,这意味着编译时间更长。

从 API 设计的角度来看,常量是一个实现细节。因此,您可能希望将此实现细节(即常量)隐藏在 .cpp 文件中已有的成员函数定义之后。

rocket.hpp中:

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

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文件中而没有通过头文件暴露给客户端(如前一种情况),改变的值该常量不可能需要重新编译客户端代码。