0

在一个看起来像这样的类中:

MyClass.h

class MyClass{

public:
    MyClass();
    int x1;
    int x2;
    int x3;
    int x4;
    int x5;

private:
    int y1;
    int y2;
};

MyClass.cpp

#include "MyClass.h"

int someFunc1(int x1, int x2){
    return x1+x2;
}

int someFunc2(int x1, int x2){
    return x1+x2;
}

MyClass::MyClass(): 
    x1(1), x2(2), x3(3), x4(4),
    y1(someFunc1(x1, x2)), y2(someFunc2(x3, x4)), x5(y1+y2){}

main.cpp

#include "MyClass.h"

int main(int argc, char **argv)
{

    MyClass myclass;

    return 0;
}

编译器的输出:

In file included from MyClass.cpp:1:
MyClass.h: In constructor ‘MyClass::MyClass()’:
MyClass.h:13:9: warning: ‘MyClass::y2’ will be initialized after [-Wreorder]
     int y2;
         ^~
MyClass.h:9:9: warning:   ‘int MyClass::x5’ [-Wreorder]
     int x5;
         ^~
MyClass.cpp:11:1: warning:   when initialized here [-Wreorder]
 MyClass::MyClass():
 ^~~~~~~
MyClass.cpp: In constructor ‘MyClass::MyClass()’:
MyClass.cpp:13:54: warning: ‘*<unknown>.MyClass::y1’ is used uninitialized in this function [-Wuninitialized]
     y1(someFunc1(x1, x2)), y2(someFunc2(x3, x4)), x5(y1+y2){}
                                                      ^~
MyClass.cpp:13:57: warning: ‘*<unknown>.MyClass::y2’ is used uninitialized in this function [-Wuninitialized]
     y1(someFunc1(x1, x2)), y2(someFunc2(x3, x4)), x5(y1+y2){}
                                                         ^~

我无法控制someFunc1and someFunc2,我只是以这种方式定义它们以编译代码。

我可以通过删除成员初始化器列表来修复这些警告,并像这样初始化构造函数主体中的数据成员:

MyClass::MyClass(){
    x1 = 1;
    x2 = 2;
    x3 = 3;
    x4 = 4;
    y1=someFunc1(x1, x2); 
    y2=someFunc2(x3, x4);
    x5=y1+y2;
}

或者我可以像这样重新排序类主体中数据成员的声明:

class MyClass{
public:
    MyClass();
    int x1;
    int x2;
    int x3;
    int x4;
private:
    int y1;
    int y2;
public:
    int x5;
};

但是在这里我不必要地声明了公共成员的范围两次!

如何修复(而不是摆脱)这些警告并仍然使用成员初始化器列表进行初始化?

如您所见,第一个原始形式中的数据成员是根据它们的用法以正确的顺序定义的,但是编译器本身仍然无法弄清楚。

4

2 回答 2

2

如您所见,第一个原始表单中的数据成员是根据其用途以正确的顺序定义的,

相反,我们可以看到相反的情况:在第一个示例中,成员根据其用途以错误的顺序声明:

    int x5;

private:
    int y1;
    int y2;

如您所见,在和x5之前声明。因此在其他两个之前初始化。y1y2x5

y1(someFunc1(x1, x2)), y2(someFunc2(x3, x4)), x5(y1+y2)

在这里,您误导了成员初始化器列表的顺序与初始化成员的顺序不同。-Wreorder警告是这种选择的结果。

此外,初始化程序使用 的y1和的值y2尚未初始化。-Wuninitialized警告是其结果。


但是在这里我不必要地声明了公共成员的范围两次!

这几乎不是问题。

如何修复(而不是摆脱)这些警告并仍然使用成员初始化器列表进行初始化?

您已经展示了两种解决方案,其中一种满足您使用成员初始化程序列表的愿望。我推荐满足您所有期望要求的解决方案。

如果您不希望更改成员的顺序,则可以调整第一个解决方案以仍然对所有其他成员使用成员初始化器列表,但依赖于后一个成员的成员除外:

MyClass::MyClass(): 
    x1(1), x2(2), x3(3), x4(4), x5{}
    y1(someFunc1(x1, x2)), y2(someFunc2(x3, x4))
{
    x5 = y1 + y2;
}

像这样的复杂初始化是构造函数体存在的目的。

于 2021-03-29T13:49:05.840 回答
1

您可以使用委托构造函数:

class MyClass{

public:
    MyClass() : MyClass(1, 2, 3, 4) {}

//private:

    MyClass(int x1, int x2, int x3, int x4) :
        MyClass(x1, x2, x3, x4, someFunc1(x1, x2), someFunc2(x3, x4))
    {}

    MyClass(int x1, int x2, int x3, int x4, int y1, int y2) :
        x1(x1), x2(x2), x3(x3), x4(x4), x5(y1 + y2), y1(y1), y2(y2)
    {}
public:
    int x1;
    int x2;
    int x3;
    int x4;
    int x5;

private:
    int y1;
    int y2;
};
于 2021-03-29T13:18:03.403 回答