【问题标题】:why we can't initialize static variable in constructor initialization list , but we can in constructor body为什么我们不能在构造函数初始化列表中初始化静态变量,但我们可以在构造函数体中
【发布时间】:2015-03-09 06:19:27
【问题描述】:

对于变量初始化,我总是优先阅读初始化列表而不是构造函数主体。我也知道静态变量可以在定义它们时在类之外初始化。

但我的问题是为什么我们不能在构造函数初始化列表中初始化静态变量,但我们可以在构造函数体中

class sample
{
    static int i;
public:
    sample (int ii=20) { i=ii;}
    void show()
    {
        cout << i << endl;
    }

};

int sample::i=12;

int main()
{
    sample s;
    s.show();
    return 0;
}

工作正常并打印 20。但我将构造函数替换为

sample (int ii=20): i(ii){}

它给出了错误。为什么?

【问题讨论】:

  • 你没有在构造函数体中初始化它。您正在为它分配一个值。
  • 因为C++是这样定义的:只能在:之后和{之前初始化非静态成员变量
  • 大家有没有看错问题?他们想知道为什么你不能在成员初始化列表中初始化一个静态成员。
  • 这能回答你的问题吗? How to initialize private static members in C++?

标签: c++ constructor


【解决方案1】:

在构造函数体内,您赋值初始化只能在初始化列表中进行。

你认为初始化静态成员只是对它的赋值。你可以自己测试一下:将静态成员设为const,你的构造函数将不再有效。

那么,构造函数初始化列表只适用于instance成员。但是,静态成员不是您的类的 instance 的成员,而是与其他类成员具有相同可见性的全局变量;因此,任何在类初始化列表中“初始化”它们的尝试实际上都是对静态成员的“重新初始化”,这在 C++ 中是被禁止的。

【讨论】:

  • 这真的回答了这个问题吗?看起来他们想知道相反的情况。为什么不能在成员初始化列表中初始化一个静态成员?
  • @JosephMansfield 我读到这个问题是因为不理解在初始化列表中初始化和在正文中初始化之间的区别。解释为什么无法在 init 列表中初始化是一种有效的回答方式,解释为什么在正文中初始化甚至没有发生是另一种有效的回答方式。
  • @JosephMansfield:同意 hvd 写的内容。但是,我意识到可能会出现混淆,并相应地编辑了我的答案。
【解决方案2】:

成员初始化列表表示初始化static 成员已在程序开始时初始化(在 main 之前)。如果您可以按照您的建议进行操作,您将使用您创建的每个 sample 对象“重新初始化”静态成员,但对象只初始化一次。

相反,如果你想在一个对象被初始化之后改变它的值,你必须给它赋值。这正是您的第一个代码对 i = ii; 所做的事情。

【讨论】:

  • 一个静态成员在你的程序启动之前已经被初始化在很多情况下都是错误的。静态成员不必是编译时常量。
  • @phresnel 静态变量在 main 之前初始化,它通常包含“程序”,所以是的,静态成员和静态全局变量在“程序”开始之前初始化。只有函数局部静态是此规则的例外。
  • @phresnel 嗯,这取决于你如何解释“在你的程序开始之前”——但我已经改写了。
  • @rubenvb:如果在 main 启动之前执行了代码,那么如果不是“正在运行的程序”,那么可以调用什么?魔法小马阶段?真心不同意你。在操作系统级别上,运行 程序 包括任何 runtime 初始化。
  • @phresnel 这有点迂腐。即使初始化程序是在编译时评估的,实际对象在您执行程序之前并不存在,因此即使那样也不会是“在程序启动之前”。我认为人们普遍认为,在这种情况下,“在程序启动之前”是指在main 开始运行之前。
【解决方案3】:

您只能初始化一次,但构造函数可能会运行多次。此外,您不应访问未初始化的内容。

假设这是允许的。然后你必须像这样回答有关代码的难题:

int foo::static_member;
foo::foo() : static_member(42){}
foo::foo(int a) : static_member(a) {}
foo::foo(double b) {}

int main()
{
  std::cout << foo::static_member;
  foo m(2.5);
}

这有意义吗?您必须更改语言的哪些部分才能使其有意义并且不会造成危险的混淆?允许这种代码的哪些好处超过了增加的混乱和复杂性?答案是,按顺序:不,太多了,根本没有。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-27
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多