【问题标题】:Error Initializing Object Array in C++在 C++ 中初始化对象数组时出错
【发布时间】:2015-06-03 07:21:14
【问题描述】:

当我运行尝试初始化对象数组的代码时,其中一个对象的值无效,它似乎没有调用构造函数,它会设置适当的默认值。下面的代码产生输出:

1
2
1528112104

玩具代码:

#include <iostream>
using namespace std;

class BeeBoop
{
    public:
        static const int MIN_X = 1;
        static const int MAX_X = 2;
        BeeBoop(int x);
        int getX() { return x; }
        bool setX(int x);

    private:
        int x;
};

int main()
{
    BeeBoop boops[] =
    {
        BeeBoop(1),
        BeeBoop(2),
        BeeBoop(3)
    };

    for (int i = 0; i < 3; i++)
        cout << boops[i].getX() << endl;
}

BeeBoop::BeeBoop (int x)
{
    if(!setX(x))
        x = MIN_X;
}

bool BeeBoop::setX(int x)
{
    if (x < MIN_X || x > MAX_X)
        return false;
    this->x = x;
    return true;
}

为什么不调用构造函数并将其设置为 BeeBoop(3) 的默认值?

更奇怪的是,如果我将初始化列表的顺序切换为

...
BeeBoop boops[] =
{
    BeeBoop(1),
    BeeBoop(3),
    BeeBoop(2)
)
...

输出变成:

1
0
2

所以它初始化为 0,这也不是默认值。

【问题讨论】:

  • 第一个想法是你没有设置this-&gt;x,而只是设置x,因此this-&gt;x永远不会被初始化。你能确认一下吗?
  • 我不确定,但如果 x 已设置,您的“检查”可能是错误的吗? if(!setX(x)) 的行为因x 的值而异,该值尚未初始化。所以从技术上讲,它可以有任何价值。如果你很幸运,它是0,在这种情况下你的代码可以工作,但不一定是这样。

标签: c++ arrays initialization


【解决方案1】:

您将名称x 用作函数参数和成员变量(可能不是一个好主意!)。因此你需要改变:

BeeBoop::BeeBoop (int x)
{
    if(!setX(x))
        x = MIN_X;
}

到:

BeeBoop::BeeBoop (int x)
{
    if(!setX(x))
        this->x = MIN_X;
}

否则你只是修改参数x而不是设置成员变量。 (或者,您可以只为参数和成员变量使用唯一名称以避免这种歧义。)

请注意,如果您在编译时启用了适当的警告 (-Wshadow),编译器将能够指出您的错误:

main.cpp: In constructor 'BeeBoop::BeeBoop(int)':
main.cpp:30:24: warning: declaration of 'x' shadows a member of 'BeeBoop' [-Wshadow]
 BeeBoop::BeeBoop (int x)
                        ^
main.cpp:14:13: note: shadowed declaration is here
         int x;
             ^
main.cpp: In member function 'bool BeeBoop::setX(int)':
main.cpp:36:25: warning: declaration of 'x' shadows a member of 'BeeBoop' [-Wshadow]
 bool BeeBoop::setX(int x)
                         ^
main.cpp:14:13: note: shadowed declaration is here
         int x;

【讨论】:

  • 就是这样。太傻了。
【解决方案2】:

类成员函数的局部变量和函数参数是隐藏类的数据成员的局部变量。

例如在名为x的构造函数参数中隐藏了数据成员x

BeeBoop::BeeBoop (int x)
{
    if(!setX(x))
        x = MIN_X;
}

因此在声明中

        x = MIN_X;

在赋值的左侧有使用的参数x。

你应该使用任何一个

        BeeBoop::x = MIN_X;

或

        this->x = MIN_X;

存在相同问题的所有函数都必须以相同的方式更新。

考虑到最好用qualofoer const声明函数getX

int getX() const { return x; }

由于类的构造函数没有说明符explicit,所以它是一个转换构造函数。这意味着你可以简单地写

BeeBoop boops[] = { 1, 2, 3 };

函数 main 可以通过以下方式简化:)

int main()
{
    for ( BeeBoop b : { 1, 2, 3 } ) 
    {
        std::cout << b.getX() << std::endl;
    }
}

程序输出将是

1
2
1

【讨论】:

    猜你喜欢
    • 2012-04-03
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 2020-12-10
    • 2012-05-28
    相关资源
    最近更新 更多