= 和 {} 之间的区别,同时使用相同的构造函数参数名称初始化成员变量
difference between = and {} while initialising member variables using the same name for constructor arguments
根据这个 answer 对成员变量和构造函数参数使用相同的名称是可以的。所以在做了一些调试之后,我想通了为什么下面的代码不起作用(class 的操作成员从未被初始化导致 switch 语句失败。)
#include <cstdio>
#include <cstdlib>
enum class Operator {
Add,
Subtract,
Multiply,
Divide
};
class Calculator {
Operator operation;
public:
Calculator(Operator operation) {
operation = operation;
}
int calculate(int a, int b) {
switch (operation) {
case Operator::Add: {
return a+b;
}
case Operator::Subtract: {
return abs(a-b);
}
case Operator::Multiply: {
return a*b;
}
case Operator::Divide: {
return a/b;
}
}
}
};
int main() {
Calculator calculator{Operator::Add};
int a = 100;
int b = 20;
printf("%d + %d = %d\n", a, b, calculator.calculate(a, b));
}
在构造函数中用 operation{operation}
替换行 operation = operation
解决了这个问题,但我仍然不明白为什么 operation = operation
与 operation{operation}
相比产生了错误的结果,什么是两者在构造函数初始化上下文中的区别;
两个标识符相同的特殊情况下赋值和成员初始化的区别:
operation = operation;
是从参数 operation
到参数 operation
的赋值。参数 operation
使成员 operation
.
黯然失色
要解决此问题,您必须编写 this->operation = operation;
。
class Calculator {
Operator operation;
public:
Calculator(Operator operation) {
this->operation = operation;
}
};
除此之外,成员初始化operation(operation)
或operation{operation}
更可取。
class Calculator {
Operator operation;
public:
Calculator(Operator operation):
operation{operation}
{
}
};
这是有效的,因为在成员初始化列表中,作用域(还)不包含参数列表(class 作用域)但是成员初始值设定项中的表达式在作用域中用参数解析(member功能范围)。
经过我草率的解释,我从cppreference.com
:
中回忆起Constructors and member initializer lists
The body of a function definition of any constructor, before the opening brace of the compound statement, may include the member initializer list, whose syntax is the colon character :, followed by the comma-separated list of one or more member-initializers, each of which has the following syntax
class-or-identifier ( expression-list(optional) ) (1)
class-or-identifier brace-init-list (2) (since C++11)
parameter-pack ... (3) (since C++11)
1) Initializes the base or member named by class-or-identifier using direct initialization or, if expression-list is empty, value-initialization
2) Initializes the base or member named by class-or-identifier using list-initialization (which becomes value-initialization if the list is empty and aggregate-initialization when initializing an aggregate)
3) Initializes multiple bases using a pack expansion
class-or-identifier - any identifier, class name, or decltype expression that names a non-static data member, a direct or virtual base, or (for delegating constructors) the class itself
expression-list - possibly empty, comma-separated list of the parameters to pass to the constructor of the base or member
braced-init-list - brace-enclosed list of comma-separated initializers and nested braced-init-lists
parameter-pack - name of a variadic template parameter pack
即对于初始值设定项
- 只有 class 标识符本身(对于委托构造函数调用)
- base class 标识符(对于 base class 构造函数调用)
- 和数据成员(对于成员初始值设定项)
被考虑但不考虑参数(任何名称)。
在成员初始值设定项(圆括号或大括号)内,成员函数的常用名称解析适用,因此,参数可能会覆盖同名成员。
根据这个 answer 对成员变量和构造函数参数使用相同的名称是可以的。所以在做了一些调试之后,我想通了为什么下面的代码不起作用(class 的操作成员从未被初始化导致 switch 语句失败。)
#include <cstdio>
#include <cstdlib>
enum class Operator {
Add,
Subtract,
Multiply,
Divide
};
class Calculator {
Operator operation;
public:
Calculator(Operator operation) {
operation = operation;
}
int calculate(int a, int b) {
switch (operation) {
case Operator::Add: {
return a+b;
}
case Operator::Subtract: {
return abs(a-b);
}
case Operator::Multiply: {
return a*b;
}
case Operator::Divide: {
return a/b;
}
}
}
};
int main() {
Calculator calculator{Operator::Add};
int a = 100;
int b = 20;
printf("%d + %d = %d\n", a, b, calculator.calculate(a, b));
}
在构造函数中用 operation{operation}
替换行 operation = operation
解决了这个问题,但我仍然不明白为什么 operation = operation
与 operation{operation}
相比产生了错误的结果,什么是两者在构造函数初始化上下文中的区别;
两个标识符相同的特殊情况下赋值和成员初始化的区别:
operation = operation;
是从参数 operation
到参数 operation
的赋值。参数 operation
使成员 operation
.
要解决此问题,您必须编写 this->operation = operation;
。
class Calculator {
Operator operation;
public:
Calculator(Operator operation) {
this->operation = operation;
}
};
除此之外,成员初始化operation(operation)
或operation{operation}
更可取。
class Calculator {
Operator operation;
public:
Calculator(Operator operation):
operation{operation}
{
}
};
这是有效的,因为在成员初始化列表中,作用域(还)不包含参数列表(class 作用域)但是成员初始值设定项中的表达式在作用域中用参数解析(member功能范围)。
经过我草率的解释,我从cppreference.com
:
The body of a function definition of any constructor, before the opening brace of the compound statement, may include the member initializer list, whose syntax is the colon character :, followed by the comma-separated list of one or more member-initializers, each of which has the following syntax
class-or-identifier ( expression-list(optional) ) (1)
class-or-identifier brace-init-list (2) (since C++11)
parameter-pack ... (3) (since C++11)
1) Initializes the base or member named by class-or-identifier using direct initialization or, if expression-list is empty, value-initialization
2) Initializes the base or member named by class-or-identifier using list-initialization (which becomes value-initialization if the list is empty and aggregate-initialization when initializing an aggregate)
3) Initializes multiple bases using a pack expansion
class-or-identifier - any identifier, class name, or decltype expression that names a non-static data member, a direct or virtual base, or (for delegating constructors) the class itself
expression-list - possibly empty, comma-separated list of the parameters to pass to the constructor of the base or member
braced-init-list - brace-enclosed list of comma-separated initializers and nested braced-init-lists
parameter-pack - name of a variadic template parameter pack
即对于初始值设定项
- 只有 class 标识符本身(对于委托构造函数调用)
- base class 标识符(对于 base class 构造函数调用)
- 和数据成员(对于成员初始值设定项)
被考虑但不考虑参数(任何名称)。
在成员初始值设定项(圆括号或大括号)内,成员函数的常用名称解析适用,因此,参数可能会覆盖同名成员。