如何保持类成员的顺序并仍具有正常工作的构造函数

时间:2019-02-11 14:54:54

标签: c++ constructor

我想拥有整洁的头文件,其中首先列出了公共成员,然后是私有成员。

class A
{
public:
    A() : y(0), z(0), x(y + z)
    {}

    int x;

private:
    int y;
    int z;
};

成员是按照声明的顺序初始化的,所以此构造函数有很多问题,因为x使用x时不会初始化y和z。

这只是我可以编写x(0)的示例,但是如果这些不是整数而是更大的类型,那将很麻烦。 为了解决这个问题,我需要先列出私有成员y和z, 然后是公共成员x。 在初始化程序列表中首先对其进行初始化的同时,有什么方法可以让我的私有成员留在底部?

如果没有,请指导我如何订购会员,因为我在网上找不到任何示例。首先列出一些公开的成员,然后列出一些私有的成员,然后更多的公开成员对我来说似乎很肮脏,但也许我错了。

4 个答案:

答案 0 :(得分:4)

使用委派的构造函数,您可以将其编写为:

class A
{
public:
    A() : A(0, 0) { }
    {}

    int x;

private:
    explicit A(int y_, int z_) : x(y_ + z_), y(y_), z(z_) { }
    int y;
    int z;
};

答案 1 :(得分:3)

作为一种语言,C ++不能很好地将实现细节保留在头文件之外,或者通常与接口分开。您在这里所做的任何事情都会让步。

一种严格的方法是不包含任何公共成员变量,并为此分离并公开纯虚拟接口(在单独的文件中)。到那时,实际的类甚至都不需要在标头中-只需在源文件中,由工厂函数引用即可-因此剩余的标头就如您所愿。这不是我推荐的方法。

无论如何,C ++中有各种实际考虑因素会限制类成员的顺序。将所有公众成员放在班上最高级是一个不错的计划A,但有时它不会奏效,我也不建议您花大力气将其付诸实践。

答案 2 :(得分:2)

  

有什么方法可以让我的私人成员在最先初始化的同时留在底部

不。成员按声明顺序初始化;没有办法解决。

如果您只希望将成员除班级顶部之外的其他地方,则可以使用基数:

struct B {
    int y;
    int z;
};


class A : B
{
public:
    A() : B{0, 0}, x(y + z)
    {}

    int x;
};
  

首先列出一些公开的成员,然后列出一些私有的成员,然后更多的公开成员对我来说似乎很肮脏,但也许我错了。

在您的情况下这不是必需的,因为您可以先放置所有私有内容,然后再放置所有公共内容。但是总的来说,使用相同的访问说明符分割声明就可以了。尽管很少需要。

答案 3 :(得分:0)

问题在于X取决于Y和Z,但是Y和Z是已知的。 您可能会寻求解决的方法:

(1)传入构造的X,而不是让构造函数创建它。

int y = 1;
int z = 40;
int x = y + z;
A(y, z, x);

(2)一个更疯狂的想法(请不要这样做,它通常表示您如何分解代码的问题)。创建一个默认对象,然后使用new放置。但是,当我看到这样的代码时,通常是使用init()函数或其他函数。对于int来说,这是一个超级杀伤力,但我假设您使用的是更复杂的类型,这就是您这样做的原因。

A() : y(0), z(0), x(/*default construct*/)
{
  new (&x) int(y + z);
}
//or
A() : y(0), z(0), x(/*default construct*/)
{
  x.init(y, z);
}

总的来说,我认为您应该重新评估X为何依赖Y和Z,并可能重新整理一些数据和职责。

如果X依赖于Y和Z的状态,则可能希望将其用作函数(如果在类外部使用它),因为作为公共成员变量,其他人可以对其进行修改并可能使其与X脱离同步和Y。您可能还想将Y和Z放在X的内部。