我可以为字段和构造函数参数使用相同的名称吗?
class C { T a; public: C(T a): a(a) {;} };
这是合法吗?
是的,这是合法的,并在所有平台上工作。 它会正确地初始化你的成员variablesa,传入值a。
尽pipe有些人认为它们有些不同,但是并不是全部。 我个人真的使用它很多:)
初始化列表具有相同的variables名称,因为初始化列表中的初始化项目的语法如下所示:
<成员>(<值>)
你可以通过创build一个简单的程序来validation我上面写的是什么:(它不会编译)
class A { A(int a) : a(5)//<--- try to initialize a non member variable to 5 { } };
你会得到一个编译错误,如:A没有一个名为“a”的字段。
在旁注:
你可能不想使用相同的成员名称作为参数名的一个原因是,你会更倾向于以下几点:
class A { A(int myVarriable) : myVariable(myVariable)//<--- Bug, there was a typo in the parameter name, myVariable will never be initialized properly { } int myVariable; };
在附注(2)上:
为什么您可能想要使用与参数名称相同的成员名称的一个原因是,您将不太容易出现以下情况:
class A { A(int myVariable_) { //<-- do something with _myVariable, oops _myVariable wasn't initialized yet ... _myVariable = myVariable_; } int _myVariable; };
这也可能发生在大型初始化列表中,并且在初始化列表中初始化之前使用_myVariable。
可能导致关于这个主题混淆的事情之一是编译器如何确定variables的优先级。 例如,如果其中一个构造函数参数与类成员具有相同的名称,则可以在初始化列表中编写以下内容:
MyClass(int a) : a(a) { }
但是上面的代码和这个效果是一样的吗?
MyClass(int a) { a=a; }
答案是不。 无论何时在构造函数体内input“a”,编译器都会首先查找一个名为“a”的局部variables或构造函数参数,只有当它找不到一个它将开始寻找一个名为“a”的类成员时, (如果没有可用的,那么将顺便寻找一个叫做“a”的全局variables)。 结果是,上面的expression式“a = a”将存储在参数“a”中的值赋予参数“a”,使其变成无用语句。
为了将参数的值赋给类成员“a”,你需要通知编译器你正在引用这个类实例中的一个值:
MyClass(int a) { this->a=a; }
好,但是如果你做了这样的事情(注意,没有一个叫做“a”的参数):
MyClass() : a(a) { }
那么在这种情况下,编译器会首先查找一个名为“a”的参数,并且当它发现没有任何它将类成员“a”的值赋给类成员“a”时,它实际上什么也不做。
最后,你应该知道你只能给初始化列表中的类成员赋值,所以下面的代码会产生一个错误:
MyClass(int x) : x(100) // error: the class doesn't have a member called "x" { }
如果forms参数和成员名称相同,那么要小心在构造函数中使用这个指针来使用成员variables
class C { T a; public: C(T a): a(a) { this->a.sort ;//correct a.sort();//will not affect the actual member variable } };
法律:是的,正如Brian所解释的那样,编译器知道在初始化器列表中期望的名称必须是成员(或基类),而不是其他任何东西。
良好的风格:很可能没有 – 对于很多程序员(包括你,似乎)结果并不明显。 对参数使用不同的名称将使代码合法,并同时使其成为一种很好的风格。
我宁愿写一些:
class C { T a_; public: C(T a): a_(a) {} }; class C { T a; public: C(T value): a(value) {} };
这种做法的问题尽pipe可能是合法的,但编译器会在使用-Wshadow时考虑variables的影子,并在其他代码中混淆这些警告。
而且,在一个不平凡的构造函数中,你犯了一个错误,忘记把这个 – >放在成员名字的前面。
Java甚至不允许这样做。 这是不好的做法,应该避免。