初始化类的私有成员变量

问题描述 投票:5回答:5

我提前道歉,因为我的一些夸夸其谈的可能不是100%正确。

我有一个这样的类:

class ClassName {
private:
    AnotherClass class2;
public:
  ClassName();
  ~ClassName();
...

在这个类的构造函数中,除其他事项外,我把线

ClassName::ClassName() {
    AnotherClass class2; 
}

这是我认为你应该在C ++中初始化的对象,但我注意到(通过GDB),正在创建了两个AnotherClass对象。一旦在构造函数的定义,然后再在我的起始线。这背后的理由?如果我想使用更复杂的构造像AnotherClass(int a, int b),它会创建一个临时对象,然后后不久建立正确的呢?

c++ class initialization
5个回答
5
投票

AnotherClass class2;创建构造函数体中,得到在身体的最后销毁内的另一个本地对象。这是类成员不是如何初始化。

类成员在构造签名和主体之间的构件初始化列表构造体之前被初始化,开始用:,像这样:

ClassName::ClassName() :
    class2(argumentsToPassToClass2Constructor),
    anotherMember(42) // just for example
{
    /* constructor body, usually empty */
}

如果你不希望任何参数传递给class2构造函数,你不必把它的初始化列表。然后它的默认构造函数将会被调用。

如果你只是想呼吁所有的类成员的默认构造函数,你可以(也应该)完全忽略构造函数。隐式生成的默认构造函数会做你想要什么。


2
投票

你在做什么在你的构造函数创建另一个变量,当地只有在构造函数中。

其实,如果你什么都不做,在AnotherClass默认的构造函数将被调用为class2对象。

如果你想成为明确的,你可以使用一个构造函数初始化列表:

ClassName::ClassName()
    : class2()
{
}

最后这个方法也调用带有参数的构造函数具体在AnotherClass,如果你需要做的的方式。


2
投票
ClassName::ClassName() {
    AnotherClass class2; // this will create local variable only
}

如果AnotherClass将有默认的构造函数,那么它会被称为由编译器class2对象。

如果你想调用参数的构造函数,那么你将不得不做,在下列方式:

ClassName::ClassName() :
    class2(arguments)

为什么要使用以及如何使用初始化列表:

请看下面的例子:

// Without Initializer List
class MyClass {
    Type variable;
public:
    MyClass(Type a) {  // Assume that Type is an already
                     // declared class and it has appropriate 
                     // constructors and operators
      variable = a;
    }
};

这里编译器符合以下步骤创建类型MyClass的的一个目的

  1. 类型的构造函数被调用首先为“A”。
  2. “类型”的赋值操作符被称为内MyClass的()构造函数的身体来分配 变量= A;
  3. 然后终于“Type”的析构函数被调用“a”,因为它超出范围。

现在考虑用初始化列表MyClass()构造相同的代码

// With Initializer List
class MyClass {
    Type variable;
public:
    MyClass(Type a):variable(a) {   // Assume that Type is an already
                     // declared class and it has appropriate
                     // constructors and operators
    }
};

随着初始化列表,下面的步骤,然后编译:

  1. Type”类的拷贝构造函数被调用初始化:variable(a)。在初始化列表的参数被用来复制构建“variable”直接。
  2. Type”的析构函数呼吁“a”,因为它超出范围。

正如我们从这个例子可以看到,如果我们使用的构造函数体内分配有三个函数调用:构造函数+析构函数+一个加法赋值运算符调用。如果我们使用初始化列表中只有两个函数调用:拷贝构造函数+析构函数调用。

这个作业处罚将是“真正的”应用中会有很多这样的变量更多。

很少有更多的场景,在这里你将不得不只使用初始化列表:

  1. 基类的构造函数参数只能通过初始化列表来调用。
  2. 为了参考的成员初始化
  3. 对于非静态常量数据成员的初始化

0
投票

你只是建立在这条线的局部变量。一般有初始化的私有成员的方式有三种:

  1. 缺省初始化

如果您在构造函数什么都不做,编译器会自动调用其默认构造函数(CTR不带参数)初始化私有成员

  1. 他们分配到的CTR体的值

在这种情况下,你必须使用赋值运算符来分配所需的价值,你的私有成员。

ClassName::ClassName()
{
    class2 = AnotherClass(a, b, c); // if the class ctr has some parameters
}
  1. 通过使用初始化列表

在你的情况下,它会是这样的:

ClassName::ClassName()
    : class2(initial_value)
{
}

这是一般用于初始化类的私有成员,因为你避免调用了传递的参数拷贝构造函数最好的和有效的选择。这是一般不是问题,除非复制CTR包含耗时的操作。这同样适用于这种情况的选项#2你可能有赋值运算符相同的问题


0
投票

你做了什么有创建一个新的变量具有相同的名称为您成员, 通过这样做,你掩盖你的成员变量。 此外,在这个过程中您的会员构造被称为默默地在类名空初始化列表。

你可以启动类有两种方式:

    ClassName::ClassName(): class2() {}

要么:

    ClassName::ClassName() {
        this->class2 = AnotherClass();
    }

第一种方式是更好的和必须的一些时间。如果你只使用你的会员空的构造函数,你会看不出来区别,除了在性能,因为编译器默认情况下,它的初始化列表初始化成员(在之后的部分“:”如果你不这样做,他再这样默默地为你...)但是,如果你的会员没有一个空的构造,例如:

    AnotherClass:: AnotherClass(int a, int b)

如果你将尝试使用在初始化的第二种方法,你会得到这样的消息:

error: constructor for 'Initiator' must explicitly initialize the member 'class2' which does not have a default constructor
© www.soinside.com 2019 - 2024. All rights reserved.