成员名称和构造函数参数名称之间的冲突

Conflicts between member names and constructor argument names

本文关键字:冲突 之间 构造函数 成员 参数      更新时间:2023-10-16

可能的重复:
成员与方法参数访问C++

我有一个类,它有一些成员,如xywidthheight。在其构造函数中,我不会这样做:

A::A(int x, int y, int width, int height)
{
x = x;
y = y;
width = width;
height = height;
}

这实际上没有意义,当用 g++ 编译时,xywidthheight变成奇怪的值(例如-1405737648)。

解决这些命名冲突的最佳方法是什么?

您可以使用具有相同名称的初始化列表:

A::A(int x, int y, int width, int height) :
x(x),
y(y),
width(width),
height(height)
{
}

另一种方法是使用不同的名称,如果您不想使用相同的名称。我想到了一些匈牙利符号的变化(我可能会对此感到有些讨厌):

//data members
int x_;
int y_;
int width_;
int height_;
//constructor
A::A(int x, int y, int width, int height) :
x_(x),
y_(y),
width_(width),
height_(height)
{
}

但第一个建议并没有错。

如果必须在构造函数中使用赋值(而不是使用首选初始值设定项列表),则解决此问题的特定模式是使用指针this如下所示:

this->a = a;

如果可能的话,最好通过初始值设定项列表设置数据成员,在这种情况下,隐藏成员名称的参数没有问题。另一种选择是在构造函数的主体中使用this->foo = foo;。资源库也存在类似的问题,但现在无法使用初始值设定项列表解决方案。你被困在this->foo = foo;- 或者只是为参数和成员使用不同的名称。

有些人真的很讨厌影子数据成员的论点;多个编码标准明确表示永远不要这样做。其他人则认为这种阴影,至少对构造者和设置者来说,是猫的喵喵声。我记得读过一两个编码标准(但我不记得是哪个)将这种阴影指定为"应该"(但不是"应该")的做法。

最后一个选项是在函数声明中使用阴影,以便为读者提供有关函数功能的提示,但在实现中使用不同的名称。

更新:什么是"阴影"?

#include <iostream>
void printi (int i) { std::cout << "i=" << i << "n"; }
int i = 21; 
int main () {
printi (i);
int i = 42; 
printi (i);
for (int i = 0; i < 3; ++i) {
printi (i);
int i = 10; 
printi (i);
}
printi (i);
}

i的最内层声明int i=10,隐藏了在for语句中声明的变量i,而i在函数作用域声明的变量又隐藏了全局变量i

在手头的问题上,参数xywidthheight到类的非默认构造函数A隐藏与这些参数同名的成员数据。

您的width=width;没有执行任何操作,因为参数width阴影(隐藏)数据成员width。当您有两个或多个在不同作用域声明的具有相同名称的变量时,获胜者始终是作用域最内侧的名称。通常,始终是具有最内层范围的名称获胜。

尽管您可以通过使用构造函数的初始化列表来避免此问题,但我建议遵循命名数据成员的约定,例如尾随_或前导m_。否则,您很可能会发生名称冲突,特别是如果您有名称为xy的成员。

class A
{
public:
A(int x, int y, int width, int height) : x_(x), y_(y), with_(width), height_(height) {}
int x_;
int y_;
int width_;
int height_;
};

您可以更改构造函数参数的名称。当你写的时候

A::A(int x, int y, int width, int height)
{
x = x;
y = y;
width = width;
height = height;
}

然后,您将构造函数的参数分配给自己,使实际的实例变量未初始化,这就是获得虚假值的原因。

我建议(并广泛使用)的一般解决方案是更改构造函数方法的参数名称:

A::A(int x_initial, int y_initial, int width_initial, int height_initial)
{
x = x_initial;
y = y_initial;
width = width_initial;
height = height_initial;
}