带有表达式的 C++ 初始化列表

C++ Initialization list with expressions

我刚刚了解到我应该在我的 C++ 构造函数中使用初始化列表而不是赋值。这是我的例子。

**赋值示例:**

Class Graph {
private:
    int count;
    int spacing;
    int width;

public:
    Graph(int _count, int _spacing, int _chart_width) {
        count = _count;
        spacing = _spacing;
        width = (_chart_width - ((_count - 1) * _spacing)) / _count;
    }
};

**初始化列表示例:**

Class Graph {
private:
    int count;
    int spacing;
    int width;

public:
    Graph(int _count, int _spacing, int _chart_width) : count(_count), spacing(_spacing), width((_chart_width - ((_count - 1) * _spacing)) / _count) {}
};

如你所见,这看起来真的很难看。

我的问题是:

  1. 这是用表达式编写初始化列表构造函数的方法吗?
  2. 有更好的语法吗?如果表达式真的很长并且使初始化列表语法完全不可读怎么办?
  3. 我是否应该编写一个方法 getWidth() 来计算 width 并清理构造函数?类似于 width(getWidth(_chart_width)).
  4. 初始化列表语法表明,例如,count(_count) 是一个将 _count 作为输入参数的函数。我是否将初始化列表语法与函数语法混淆了?或者 count() 真的是一个函数吗?这很令人困惑。
  5. 如果我编写初始化列表的方式是正确的,您能否建议一种更好的方式来格式化代码以提高可读性?我想,我想知道长初始化列表最常见的语法是什么。

不同的项目(和人)有不同的编码标准和品味,但我个人觉得这种格式非常易读:

Class Graph {
  private:
    int count;
    int spacing;
    int width;

  public:
    Graph(int _count, int _spacing, int _chart_width)
        : count(_count), spacing(_spacing),
          width((_chart_width - ((_count - 1) * _spacing)) / _count)
    {}
};

不,这些不一定是函数调用。但它们可以是... 最好的思考方式如下:如果您正在初始化的变量是 class 的实例,那么您正在调用构造函数来初始化它们。如果你这样看,语法就有意义了。

而且我会推荐一个辅助函数(作为 class 的私有方法,也许是静态方法)来计算宽度。

Is this the way to write an Initialization list constructor with expressions?

是的,它是(尽管您可以将其格式化以使其更具可读性)。

Is there a better syntax? What if the expression is really long and makes the Initialization list syntax completely unreadable?

我不知道。如果列表太长,您可以按行格式化列表。如果您的参数初始化非常长、复杂且几乎不可读(即需要 2-3 行并且充满逻辑),我建议将其移至构造函数的主体。作为一般经验法则,初始化列表用于执行此操作:初始化。出于以下几个原因,您不应该在列表参数中执行逻辑块:

  1. 如果您的参数需要一个小的数学方程式,那很好,但除此之外的任何东西都可能需要它自己的函数。它也可以在对象的构造函数中完成,您可以在其中使用名称变量来表示正在发生的事情。

  2. "Clean Code"的一般规则是不要自作聪明。如果某些内容不可读,您应该积极努力让您的同龄人能够理解它。

  3. 查看下一个问题的答案。

Should I write a method getWidth() that computes the width and cleans up the constructor? Something like width(getWidth(_chart_width)).

  1. 在初始化列表的参数中使用函数调用是完全可以接受的。为了可读性,我什至鼓励您这样做。归根结底,初始化列表的主要功能之一是从构造函数中删除可能填充它的 "x = _x" 行,并为不只是分配值的函数腾出一些空间。

Initialization list syntax indicates that, for example, count(_count) is a function that takes in _count as an input argument. Am I mixing up the Initialization list syntax with function syntax? or is count() truly a function? This is very confusing.

基本上,C++ 正在创建一个隐式函数来将传递的参数分配给适当的变量。将此视为 C++ 创建了一堆如下所示的不可见函数:

aType setVarName(aType aParam)
{
    varName = aParam;
}

If the way I am writing the Initialization list is correct, can you please suggest a better way to format the code for readability? I guess, I would like to know what is the most common syntax for long Initialization lists.

您的初始化列表应该与您定义构造函数的位置相同。在您提供的示例中,您的构造函数是空的,因此您决定在头文件中定义它,这样您也可以在那里定义列表。我知道这不适用于您的情况,但最好记住,如果您的构造函数确实有内容,您应该在“.cpp”文件中的构造函数块上方定义列表,如下所示:

Graph(int _count, int _spacing, int _chart_width) : 
count(_count),
spacing(_spacing), 
width((_chart_width - ((_count - 1) * _spacing)) / _count) 
{
    ...
    [your constructor's code here]
    ...
}

我被教导你应该用一个新行分隔每个参数,但正如雨城所说:"Different projects (and people) have different coding standards and tastes"。

尽管如此,我还是建议不要将其全部写在一行中,因为如果它变大会严重影响其可读性。您通常希望避免需要 "portrait monitor" 用户必须水平滚动的行。

编辑:我注意到你在另一条评论中说你有 java 的背景,并且想知道 int 与对象背后的逻辑。虽然我不确定 Java 是否这样做,但 C++ 做了很多隐式函数定义,它将 "silently" 生成函数来完成一些常见的行为。例如,对象可以有一个隐式复制构造函数,它允许您通过将另一个相同类型的对象传递给一个对象来创建一个对象的实例。然而,在初始化列表的情况下,它们只是为变量赋值的隐式函数。我建议您阅读 C++ 中隐式函数的不同情况,以便全神贯注。

我的问题是:

  1. 这是用表达式编写初始化列表构造函数的方法吗?

  1. 有没有更好的语法?如果表达式真的很长并且使初始化列表语法完全不可读怎么办?

使用多行并在行变长时缩进。

  1. 我是否应该编写一个方法 getWidth() 来计算宽度并清理构造函数?像 width(getWidth(_chart_width)).
  2. 这样的东西

是的,你可以这样做,但它不能是同一个 class 的实例方法,因为你还没有 "this"。

  1. 初始化列表语法表明,例如,count(_count) 是一个将_count 作为输入参数的函数。我是否将初始化列表语法与函数语法混淆了?还是 count() 真的是一个函数?这很令人困惑。

语法相同。代码中的位置将其标识为初始化而非函数调用(在构造函数签名后的“:”字符之后)。不,count 不是函数,它只是一种指示,对于 x(y),用 y 初始化 x。在 C++ 中,相同的语法可以用于不同的事物,它们通过它们周围的上下文来区分。你会发现 x(y) 语法用于 C++ 中的其他事物(宏是一个,强制转换是另一个,superclass 初始化是另一个)。

  1. 如果我编写初始化列表的方式是正确的,您能否建议一种更好的方式来格式化代码以提高可读性?我想,我想知道长初始化列表最常见的语法是什么。

多用一行就行了。可以在任何有空格的地方使用新行。当您使用新行时,使用额外的缩进。您可以发挥一点创意,也可以参考编码标准文档来寻找思路。这很好:

Graph(int _count, int _spacing, int _chart_width) : 
    count(_count), 
    spacing(_spacing),
    width((_chart_width - (_count - 1) * _spacing) / _count) {}

或者如果参数很多,你可以这样做:

Graph(int _count,
     int _spacing,
     int _chart_width) : 
        count(_count), 
        spacing(_spacing),
        width((_chart_width - (_count - 1) * _spacing) / _count) {}