提问者:小点点

在参数化构造函数中使用此指针


当我将参数传递给构造函数并在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)
         {};

共3个答案

匿名用户

因为名字不一致。 如果在示例中编写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