如何在构造函数中初始化C++对象成员变量?

Log*_*acy 66 c++ constructor object-construction class-members

我有一个类有几个对象作为成员变量.我不希望在声明时调用这些成员的构造函数,所以我试图明确地挂起指向该对象的指针.我不知道我在做什么.O_O

在StackOverflow上,我似乎能够找到对象成员变量的其他示例,但通常会立即调用构造函数,如下所示:

class MyClass {
    public:
        MyClass(int n);
    private:
        AnotherClass another(100); // this constructs AnotherClass right away!
};
Run Code Online (Sandbox Code Playgroud)

但我希望MyClass构造函数调用AnotherClass构造函数.这是我的代码的样子:

BigMommaClass.h

#include "ThingOne.h"
#include "ThingTwo.h"

class BigMommaClass {

        public:
                BigMommaClass(int numba1, int numba2);

        private:
                ThingOne* ThingOne;
                ThingTwo* ThingTwo;
};
Run Code Online (Sandbox Code Playgroud)

BigMommaClass.cpp

#include "BigMommaClass.h"

BigMommaClass::BigMommaClass(int numba1, int numba2) {
        this->ThingOne = ThingOne(100);
        this->ThingTwo = ThingTwo(numba1, numba2);
}
Run Code Online (Sandbox Code Playgroud)

这是我尝试编译时遇到的错误:

g++ -Wall -c -Iclasses -o objects/BigMommaClass.o classes/BigMommaClass.cpp
In file included from classes/BigMommaClass.cpp:1:0:
classes/BigMommaClass.h:12:8: error: declaration of âThingTwo* BigMommaClass::ThingTwoâ
classes/ThingTwo.h:1:11: error: changes meaning of âThingTwoâ from âclass ThingTwoâ
classes/BigMommaClass.cpp: In constructor âBigMommaClass::BigMommaClass(int, int)â:
classes/BigMommaClass.cpp:4:30: error: cannot convert âThingOneâ to âThingOne*â in assignment
classes/BigMommaClass.cpp:5:37: error: â((BigMommaClass*)this)->BigMommaClass::ThingTwoâ cannot be used as a function
make: *** [BigMommaClass.o] Error 1
Run Code Online (Sandbox Code Playgroud)

我使用正确的方法但语法错误吗?或者我应该从另一个方向来到这个?

chr*_*ris 87

您可以在成员初始化列表中指定如何初始化成员:

BigMommaClass {
    BigMommaClass(int, int);

private:
    ThingOne thingOne;
    ThingTwo thingTwo;
};

BigMommaClass::BigMommaClass(int numba1, int numba2)
    : thingOne(numba1 + numba2), thingTwo(numba1, numba2) {}
Run Code Online (Sandbox Code Playgroud)

  • 使用这种语法仍然困扰我,我不能在构造函数中做任何真正的工作来传递给其他构造函数.构造函数应该是轻量级的,所以我无法想出一个真实的例子,但我发现自己希望语法看起来更像是`this.thingOne = new ThingOne(100);`因为它只是提供了更多的灵活性.但我离题了. (20认同)

Yuu*_*shi 27

您正在尝试创建一个ThingOne使用operator=哪个不起作用(语法不正确).此外,您正在使用类名作为变量名,即ThingOne* ThingOne.首先,让我们修复变量名称:

private:
    ThingOne* t1;
    ThingTwo* t2;
Run Code Online (Sandbox Code Playgroud)

由于这些是指针,它们必须指向某些东西.如果尚未构造对象,则需要在BigMommaClass构造函数中使用new显式执行此操作:

BigMommaClass::BigMommaClass(int n1, int n2)
{
    t1 = new ThingOne(100);
    t2 = new ThingTwo(n1, n2);
}
Run Code Online (Sandbox Code Playgroud)

通常初始化列表是构造的首选,因此它看起来像:

BigMommaClass::BigMommaClass(int n1, int n2)
    : t1(new ThingOne(100)), t2(new ThingTwo(n1, n2))
{ }
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.那么我应该使用`ThingOne*t1`还是应该使用`ThingOne t1`? (2认同)
  • @DavidEnglund,使用后者.不必要的动态分配很糟糕.如果你真的需要它,那么智能指针将是最佳选择. (2认同)

pat*_*ato 8

这个问题有点旧,但是在初始化成员变量之前,这是构造函数中"做更多工作"的c ++ 11的另一种方式:

BigMommaClass::BigMommaClass(int numba1, int numba2)
    : thingOne([](int n1, int n2){return n1+n2;}(numba1,numba2), 
      thingTwo(numba1, numba2) {}
Run Code Online (Sandbox Code Playgroud)

将调用上面的lambda函数,并将结果传递给thingOnes构造函数.你当然可以让lambda变得如你所愿.


Iva*_*van 6

我知道这是 5 年后的事,但上面的答复并没有解决您的软件出了什么问题。(嗯,Yuushi 的确实如此,但直到我输入这个我才意识到 - 哦!)。他们回答了标题如何在构造函数中初始化 C++ 对象成员变量中的问题?这是关于其他问题:我是否使用了正确的方法但使用了错误的语法?或者我应该从不同的方向来解决这个问题?

编程风格在很大程度上取决于意见,但在构造函数中尽可能多做的另一种观点是将构造函数保持在最低限度,通常具有单独的初始化函数。没有必要尝试将所有初始化都塞进构造函数中,更不用说有时尝试将某些东西强制放入构造函数初始化列表中。

那么,说到点子上,你的软件出了什么问题?

private:
    ThingOne* ThingOne;
    ThingTwo* ThingTwo;
Run Code Online (Sandbox Code Playgroud)

请注意,在这些行之后,ThingOne(和ThingTwo) 现在有两个含义,具体取决于上下文。

在 BigMommaClass 之外,ThingOne是您创建的类#include "ThingOne.h"

BigMommaClass 内部ThingOne是一个指针。

那是假设编译器甚至可以理解这些行,并且不会陷入循环,认为它 ThingOne是指向某事物的指针,而该指针本身是指向某事物的指针,而该指针又是指向 ...

以后写的时候

this->ThingOne = ThingOne(100);
this->ThingTwo = ThingTwo(numba1, numba2);
Run Code Online (Sandbox Code Playgroud)

请记住,BigMommaClass您的内部ThingOne是一个指针。

如果您更改指针的声明以包含前缀 (p)

private:
    ThingOne* pThingOne;
    ThingTwo* pThingTwo;
Run Code Online (Sandbox Code Playgroud)

然后ThingOne将始终引用类和pThingOne指针。

然后可以重写

this->ThingOne = ThingOne(100);
this->ThingTwo = ThingTwo(numba1, numba2);
Run Code Online (Sandbox Code Playgroud)

作为

pThingOne = new ThingOne(100);
pThingTwo = new ThingTwo(numba1, numba2);
Run Code Online (Sandbox Code Playgroud)

它纠正了两个问题:双重含义问题和缺失的new. (this->如果你愿意,你可以离开!)

有了这些,我可以将以下几行添加到我的 C++ 程序中,它可以很好地编译。

class ThingOne{public:ThingOne(int n){};};
class ThingTwo{public:ThingTwo(int x, int y){};};

class BigMommaClass {

    public:
            BigMommaClass(int numba1, int numba2);

    private:
            ThingOne* pThingOne;
            ThingTwo* pThingTwo;
};

BigMommaClass::BigMommaClass(int numba1, int numba2)
{
    pThingOne = new ThingOne(numba1 + numba2);
    pThingTwo = new ThingTwo(numba1, numba2);
};
Run Code Online (Sandbox Code Playgroud)

当你写

this->ThingOne = ThingOne(100);
this->ThingTwo = ThingTwo(numba1, numba2);
Run Code Online (Sandbox Code Playgroud)

的使用this->告诉编译器左侧ThingOne是指指针。但是我们BigMommaClass当时在里面,没有必要。

问题在于等号的右侧,其ThingOne意在表示班级。所以另一种纠正你的问题的方法是写

this->ThingOne = new ::ThingOne(100);
this->ThingTwo = new ::ThingTwo(numba1, numba2);
Run Code Online (Sandbox Code Playgroud)

或者干脆

ThingOne = new ::ThingOne(100);
ThingTwo = new ::ThingTwo(numba1, numba2);
Run Code Online (Sandbox Code Playgroud)

通过::改变标识的编译器的解释。