C++ 我可以对字段和构造函数参数使用相同的名称吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/268587/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I use identical names for fields and constructor parameters?
提问by Sergey Skoblikov
class C {
T a;
public:
C(T a): a(a) {;}
};
Is it legal?
合法吗?
采纳答案by Brian R. Bondy
Yes it is legal and works on all platforms. It will correctly initialize your member variable a, to the passed in value a.
是的,它是合法的,适用于所有平台。它将正确地将您的成员变量 a 初始化为传入的值 a。
It is considered by some more clean to name them differently though, but not all. I personally actually use it a lot :)
一些更干净的人认为以不同的方式命名它们,但不是全部。我个人实际上经常使用它:)
Initialization lists with the same variable name works because the syntax of an initialization item in an initialization list is as follows:
具有相同变量名的初始化列表之所以有效,是因为初始化列表中的初始化项的语法如下:
<member>(<value>)
<成员>(<值>)
You can verify what I wrote above by creating a simple program that does this: (It will not compile)
您可以通过创建一个执行此操作的简单程序来验证我上面写的内容:(它不会编译)
class A
{
A(int a)
: a(5)//<--- try to initialize a non member variable to 5
{
}
};
You will get a compiling error something like: A does not have a field named 'a'.
您将收到类似以下的编译错误:A 没有名为“a”的字段。
On a side note:
旁注:
One reason why you may not wantto use the same member name as parameter name is that you would be more prone to the following:
您可能不想使用与参数名称相同的成员名称的原因之一是您更容易出现以下情况:
class A
{
A(int myVarriable)
: myVariable(myVariable)//<--- Bug, there was a typo in the parameter name, myVariable will never be initialized properly
{
}
int myVariable;
};
On a side note(2):
附注(2):
One reason why you may wantto use the same member name as parameter name is that you would be less prone to the following:
您可能希望使用与参数名称相同的成员名称的原因之一是您不太容易出现以下情况:
class A
{
A(int myVariable_)
{
//<-- do something with _myVariable, oops _myVariable wasn't initialized yet
...
_myVariable = myVariable_;
}
int _myVariable;
};
This could also happen with large initialization lists and you use _myVariable before initializing it in the initialization list.
这也可能发生在大型初始化列表中,并且您在初始化列表中初始化它之前使用了 _myVariable。
回答by Dragonion
One of the things that may lead to confusion regarding this topic is how variables are prioritized by the compiler. For example, if one of the constructor arguments has the same name as a class member you could write the following in the initialization list:
可能导致与此主题相关的混淆的一件事是编译器如何确定变量的优先级。例如,如果构造函数参数之一与类成员同名,您可以在初始化列表中写入以下内容:
MyClass(int a) : a(a)
{
}
But does the above code have the same effect as this?
但是上面的代码和这个效果一样吗?
MyClass(int a)
{
a=a;
}
The answer is no. Whenever you type "a" inside the body of the constructor the compiler will first look for a local variable or constructor argument called "a", and only if it doesn't find one will it start looking for a class member called "a" (and if none is available it will then look for a global variable called "a", by the way). The result is that the above statment "a=a" will assign the value stored in argument "a" to argument "a" rendering it a useless statement.
答案是不。每当您在构造函数的主体中键入“a”时,编译器将首先查找名为“a”的局部变量或构造函数参数,并且只有在找不到时才会开始查找名为“a”的类成员(如果没有可用的,它会寻找一个名为“a”的全局变量,顺便说一句)。结果是上面的语句“a=a”会将存储在参数“a”中的值分配给参数“a”,从而使其成为无用的语句。
In order to assign the value of the argument to the class member "a" you need to inform the compiler that you are referencing a value inside thisclass instance:
为了将参数的值分配给类成员“a”,您需要通知编译器您正在引用此类实例中的一个值:
MyClass(int a)
{
this->a=a;
}
Fine, but what if you did something like this (notice that there isn't an argument called "a"):
很好,但是如果你做这样的事情会怎样(注意没有一个名为“a”的参数):
MyClass() : a(a)
{
}
Well, in that case the compiler would first look for an argument called "a" and when it discovered that there wasn't any it would assign the value of class member "a" to class member "a", which effectively would do nothing.
那么,在这种情况下,编译器首先会寻找一个名为“a”的参数,当它发现没有任何参数时,它会将类成员“a”的值分配给类成员“a”,这实际上什么也不做.
Lastly you should know that you can only assign values to class members in the initialization list so the following will produce an error:
最后,您应该知道您只能为初始化列表中的类成员赋值,因此以下将产生错误:
MyClass(int x) : x(100) // error: the class doesn't have a member called "x"
{
}
回答by yesraaj
if the formal parameter and the member is named same then beware of using this pointer inside constructor to use the member variable
如果形式参数和成员名称相同,则要注意在构造函数中使用此指针来使用成员变量
class C {
T a;
public:
C(T a): a(a) {
this->a.sort ;//correct
a.sort();//will not affect the actual member variable
}
};
回答by Suma
Legal: yes, as explained by Brian, compiler knows the name to expect in the initializer list must be a member (or a base class), not anything else.
合法:是的,正如 Brian 所解释的,编译器知道初始化列表中的名称必须是成员(或基类),而不是其他任何东西。
Good style: most likely not - for a lot of programmers (including you, it seems) the result is not obvious. Using a different name for the parameter will keep the code legal and make it a good style at the same time.
好的风格:很可能不是 - 对于很多程序员(包括你,似乎)结果并不明显。为参数使用不同的名称将保持代码合法并同时使其成为一种良好的风格。
I would prefer writing some of:
我更喜欢写一些:
class C {
T a_;
public:
C(T a): a_(a) {}
};
class C {
T a;
public:
C(T value): a(value) {}
};
回答by Rick
The problem with this practice, legal though it may be, is that compilers will consider the variables shadowed when -Wshadow is used, and it will obfuscate those warnings in other code.
这种做法的问题(尽管可能是合法的)是编译器会考虑使用 -Wshadow 时隐藏的变量,并且会在其他代码中混淆这些警告。
Moreover, in a non-trivial constructor, you make make a mistake, forgetting to put this-> in front of the member name.
此外,在一个非平凡的构造函数中,你犯了一个错误,忘记把 this-> 放在成员名的前面。
Java doesn't even allow this. It's bad practice, and should be avoided.
Java 甚至不允许这样做。这是不好的做法,应该避免。