c ++在构造函数中使用class成员作为参数

c++ Using class member as a parameter in constructor

我有一个 class,我需要使用其中一个成员作为构造函数参数来初始化相同 class 的另一个 const 成员。

class A
{
private:
   M1Type m1;
   const M2Type m2;
public:
   A(x) : m1(x), m2(m1){}
};

这是初始化 m2 的正确方法吗?列表初始化中m1的构造完成了吗?

更新: 抱歉,我错过了 x 的类型(更像是一个伪代码)。假设任何原始类型。

是的,“m1 的构造完成”当它用于初始化 m2 并且如果 M2Type 可以从 [=14= 构造], 这很好 - 但 x 需要 A(x).

中的类型

初始化顺序是您在 class 中定义成员变量的顺序,而不是您在成员初始化列表中使用它们的顺序:

M1Type m1;
const M2Type m2;

A(M1Type x) : m2(m1), m1(x) {} // wrong order, but still ok

如果 x 的类型可用于构造 M1TypeM2Type 并获得与构造 M2Type 相同的结果M1Typex 构造而成,您不妨使用 x 构造两者,以免以后重组成员变量时出现问题。但这并不总是可能的。

示例:

struct M1Type {
    explicit M1Type(double) {};
};

struct M2Type {
    explicit M2Type(M1Type) {}
};

class A {
public:
   M1Type m1;
   const M2Type m2;
public:
   // error: no matching function for call to 'M2Type::M2Type(double&)':
   // A(double x) : m1(x), m2(x) {}

   A(double x) : m1(x), m2(m1) {}   // OK
};

成员按照它们在 class 定义中出现的顺序进行初始化(与初始化列表中的顺序无关)。因此,首先 m1 被初始化,你可以使用它的值来初始化 m2.

这个代码

class A
{
private:
   M1Type m1;
   const M2Type m2;
public:
   A(int x) : m1(x), m2(m1){}
};

很好(除了 x 的缺失类型)。不过,如果可能的话,我宁愿这样写:

class A
{
private:
   M1Type m1;
   const M2Type m2;
public:
   A(int x) : m1(x), m2(x){}
};

因为现在正确性不取决于成员的顺序。重构时它可能会改变。编译器通常会在初始化列表中的顺序不同时发出警告,但您可以依赖正确的代码而不是依靠警告,而不管成员的顺序是什么。


请注意,编译器不一定会针对此代码发出警告(交换成员的顺序):

class A
{
private:
   const M2Type m2;
   M1Type m1;

public:
   A(int x) : m2(m1),m1(x) {}  // !! most likely UB !!
};

但如果 M2Type 的构造函数使用 m1 的值,它具有未定义的行为,因为 m1 未初始化使用。因此,在成员初始化相互依赖时要小心。

假设 M2Type 的构造函数接受应该工作的 M1Type 参数。

PS: A(x) - 应指定 x 的类型。

执行下面的代码可以确保它有效:

#include <iostream>
class M1Type
{
public:
    int iField;
    M1Type(int x): iField{x}
    {
        std::cout << "M1Type(int x)" << iField << std::endl;
    }
};
class M2Type
{
public:
    int iField;
    M2Type(M1Type m1) : iField{ m1.iField + 500 }
    {
        std::cout << "M2Type(M1Type m1)" << iField << std::endl;
    }
};
class A
{
private:
    M1Type m1;
    const M2Type m2;
public:
    A(int x) : m1(x), m2(m1) 
    {
        std::cout << "A(int x): M1Type: " << m1.iField << "; M2Type: " << m2.iField << std::endl;
    }
};
int main()
{
    A objA(73);
}

控制台输出为:

M1Type(int x)73
M2Type(M1Type m1)573
A(int x): M1Type: 73; M2Type: 573