当我将参数传递给构造函数并在body内部执行赋值时,我必须使用此指针,否则它将无法运行。
class Employee
{
public:
string name;
const char *id;
int age;
long salary;
Employee (string name,const char* id, int age, long salary)
{
this->name = name;
this->id = id;
this->age = age;
this->salary = salary;
};
};
但是如果我使用其他方法,那么就不需要这个指针了。 为什么会这样呢?
Employee(string name,const char id[], int age, long salary): name(name),id(id),age(age),salary(salary)
{};
因为名字不一致。 如果在示例中编写name=name
,则是将局部变量name
赋给其自身。
通过使用this
,您可以明确地引用您的对象,从而明确地声明您希望分配name
成员。
初始值设定项列表之所以能工作,是因为只有成员才能出现在其中。 但是考虑一下当您(假设)希望用成员name
初始化成员id
时会发生什么(不考虑参数)。 在这种情况下,this->name
再次变得必要。
可以通过对成员或参数进行不同的命名来避免整个问题,例如M_
是一个常见的约定:M_name=name
在第一种情况下,构造函数的参数阴影了类的字段。 您需要this->
来指定要将值分配给哪个变量。 在第二种情况下,您使用一个初始化列表。 (更多信息请点击这里:https://isocpp.org/wiki/faq/ctors#init-lists)
对于第一种情况,在构造函数主体中,不合格的名称总是在构造函数作用域中找到,并引用构造函数参数。 则名称查找停止,包括类作用域在内的进一步作用域将不被检查。 然后,当您要指定数据成员时,必须像this->name
那样显式限定,否则,name=name;
意味着自己分配name
。
对于第二种情况,数据成员由成员初始化器列表初始化(顺便说一句,这不是第一种情况下的赋值)。 从[class.base.init]/2,
(重点为地雷)
在mem-initializer-id中,在构造函数的类的作用域中查找初始的非限定标识符,如果在该作用域中找不到,则在包含构造函数定义的作用域中查找。 [注意:如果构造函数的类包含与类的直接基类或虚拟基类同名的成员,则命名该成员或基类并由单个标识符组成的mem-initializer-id引用类成员。可以使用限定名指定隐藏基类的mem-initializer-id.-结束注意]除非mem-initializer-id命名构造函数的类,构造函数的类的非静态数据成员或该类的直接基或虚拟基,否则mem-initializer-id是错误的。
这意味着,mem-initializer-id将在类的作用域中查找,它不会也不能引用构造函数参数。
另一方面,[class.base.init]/15,
mem初始值设定项的expression-list或braced-init-list中的名称在为其指定mem初始值设定项的构造函数的作用域中求值。
在构造函数的作用域中查找初始值表达式中的名称,然后找到构造函数参数。 因此name(name)
意味着通过构造函数参数name
初始化数据成员name
。