【问题标题】:Proper setter and getter for static member variable in header-only library仅标头库中静态成员变量的正确设置器和获取器
【发布时间】:2017-08-10 12:25:25
【问题描述】:

我有一些小的 header-only 库(header-only 部分很重要)。在最初的版本中,我在其中定义的类中有一些静态成员。直到后来(当我在一个更大的项目中使用它们时)我才意识到静态成员会违反 ODR。我想让它们只保留标题,因此在单独的 .cpp 文件中定义静态成员是不可能的。一个众所周知的解决方案是为每个静态成员使用 Meyers 单例 函数局部静态变量(如建议的那样,例如,here)。

这一切都很好,但是由于我希望单例的行为类似于成员变量,因此我希望能够使用 setter 和 getter 获取和设置值。但是 Meyers 单例 函数局部静态变量的 getter 和 setter 是什么样的呢?我还没有找到任何解决该特定问题的方法。

为了澄清,这些是要求:

  • 我想要 header-only 库中的 静态成员变量 的行为(因此我不能将定义放在 .cpp 文件中)
  • 我想要一个 getter only 的 getter(我不应该通过分配给 getter 返回的引用来修改值)
  • 我还希望能够通过专用的setter修改值。

编辑 1:

我想解释一下为什么你可能需要这个。

我提到的库中的静态变量定义了一些参数的默认值。但是,我不想硬编码这些默认值,而是让用户可以在程序开始时设置默认值,这样他们就不必在每次调用成员函数或构造一个成员函数时手动传递值新实例。

此外,虽然我同意在此处提供的示例中使用术语“Meyers 单例”具有误导性(我只是使用 int 值),但没有什么能阻止您将此范例与自定义类一起使用你只想要一个实例。在这种情况下,“Meyers singleton”一词是合理的。


编辑 2:

这与在 C++17 中引入 inline static 变量有些无关,但我会把它留给没有选择使用 C++17 的人。

【问题讨论】:

  • 我不明白 setter 对单身人士有何意义。如果它是单例,则没有第二个实例可以传递给 set()
  • @tobi303 我认为“Meyers 单例”模式可能命名错误。 OP 从未说过班级本身必须是单身人士。只是他们想要一个类的静态实例,我认为“Meyers 单例”模式很适合。
  • 我想要一个静态成员变量的功能,实现它的方法是为该变量设置一个 Meyers 单例,这样我就不必在类之外定义它。那有意义吗?在我的库中,这些静态变量定义了一些默认值,但我希望能够从类外部设置这些默认值。
  • 是的,虽然我不会称它为 Meyers singelton,但我的意思是它的策略相同,但这里没有单例
  • @ChrisDrew 是的,除了我想要变量的静态实例,而不是类本身。我想只保留库标题。

标签: c++ singleton getter-setter static-members header-only


【解决方案1】:

解决方案

#include <iostream>

class Foo
{

    private:

        static int& val()
        {
            static int v = 0;
            return v;
        }

    public:

        Foo()
        {
            set_val(14);
        }

        Foo(const int _v)
        {
            set_val(_v);
        }

        // The setter uses the fact that val()
        // returns a non-const reference,
        // so we can assign to it.
        static void set_val(const int _v)
        {
            val() = _v;
        }           

        // A true getter.
        // Returns const int&, so we cannot assign to it.
        static const int& get_val()
        {
            return val();
        }
};

int main(void)
{

    std::cout << "val is " << Foo::get_val() << "\n";
    Foo f1; // Set the value implicitly via an object constructor
    std::cout << "val is " << Foo::get_val() << "\n";
    Foo f2(5); // Set the value explicitly via an object constructor
    std::cout << "val is " << Foo::get_val() << "\n";
    Foo::set_val(42);
    std::cout << "val is " << Foo::get_val() << "\n";
    // Foo::get_val() = 4; // Doesn't compile, as required

    return 0;
}

输出:

val is 0
val is 14
val is 5
val is 42

可以(并且可能应该)省略通过构造函数设置值。我只是想证明这是可以做到的。这是针对一个变量的大量代码,但并没有那么多比一个非静态成员多。

欢迎任何想法、cmets 和建议!

【讨论】:

    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 2014-04-06
    相关资源
    最近更新 更多