class C {
T a;
public:
C(T a): a(a) {;}
};
合法吗?
答案 0 :(得分:50)
是的,它是合法的,适用于所有平台。 它会正确地将您的成员变量a初始化为传入的值a。
虽然有些人认为它们更加干净,但却不是全部。我个人实际上经常使用它:))
具有相同变量名的初始化列表有效,因为初始化列表中初始化项的语法如下:
<&构件GT;(小于值GT)
您可以通过创建一个执行此操作的简单程序来验证我上面写的内容:(它不会编译)
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。
答案 1 :(得分:19)
可能导致对此主题产生混淆的一个原因是编译器如何对变量进行优先级排序。例如,如果其中一个构造函数参数与类成员具有相同的名称,则可以在初始化列表中编写以下内容:
MyClass(int a) : a(a)
{
}
但上面的代码与此有相同的效果吗?
MyClass(int a)
{
a=a;
}
答案是否定的。每当在构造函数体内键入“a”时,编译器将首先查找名为“a”的局部变量或构造函数参数,并且只有在找不到它时才会开始查找名为“a”的类成员。 (如果没有可用的话,它将寻找一个名为“a”的全局变量,顺便说一下)。结果是上面的语句“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"
{
}
答案 2 :(得分:9)
如果形式参数和成员命名相同,那么请注意在构造函数中使用此指针来使用成员变量
class C {
T a;
public:
C(T a): a(a) {
this->a.sort ;//correct
a.sort();//will not affect the actual member variable
}
};
答案 3 :(得分:4)
法律:是的,正如Brian所解释的,编译器知道初始化列表中期望的名称必须是成员(或基类),而不是其他任何名称。
好的风格:很可能不是 - 对于很多程序员(包括你,似乎)来说,结果并不明显。为参数使用不同的名称将使代码保持合法,并使其同时成为一种好的风格。
我更喜欢写一些:
class C {
T a_;
public:
C(T a): a_(a) {}
};
class C {
T a;
public:
C(T value): a(value) {}
};
答案 4 :(得分:2)
这种做法的问题虽然可能是合法的,但编译器会在使用-Wshadow时考虑阴影的变量,并且会在其他代码中模糊这些警告。
此外,在一个非平凡的构造函数中,你犯了一个错误,忘了把这个 - &gt;在会员名称前面。
Java甚至不允许这样做。这是不好的做法,应该避免。
答案 5 :(得分:0)
嘿伙计们,这是一个很好的问题。如果您想为字段和构造函数参数/方法参数使用相同的名称,您必须使用范围解析( ::
)运算符,或者您可以使用此( this->
)将参数值与这样的成员进行映射仔细检查代码片段,您可以轻松理解。
class Student{
private :
string name;
int rollNumber;
public:
Student()
{
// default constructor
}
// parameterized constructor
Student(string name, int rollNumber)
{
this->name = name;
Student::rollNumber = rollNumber;
}
void display()
{
cout<<"Name: "<<name <<endl;
cout<<"Roll Number: "<<rollNumber<<endl;
}
void setName(string name)
{
this->name = name;
}
void setrollNumber(int rollNumber)
{
Student::rollNumber = rollNumber;
}
};