我可以对字段和构造函数参数使用相同的名称吗?

Can I use identical names for fields and constructor parameters?

本文关键字:字段 构造函数 参数 我可以      更新时间:2023-10-16

class C {
  T a;
public:
  C(T a): a(a) {;}
};

合法吗?

是的,它是合法的,适用于所有平台。它会正确地将成员变量 a 初始化为传入的值 a。

有些人认为以不同的方式命名它们更干净,但不是全部。 我个人实际上经常使用它:)

具有相同变量名的初始化列表之所以有效,是因为初始化列表中初始化项的语法如下所示:

<成员>(<值>(

您可以通过创建一个简单的程序来验证我上面写的内容:(它不会编译(

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。

可能导致有关此主题的混淆的一件事是编译器如何确定变量的优先级。例如,如果其中一个构造函数参数与类成员同名,则可以在初始化列表中编写以下内容:

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"
{
}

如果形式参数和成员被命名相同,那么请注意在构造函数中使用此指针来使用成员变量

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) {}
};

这种做法的问题,尽管可能是合法的,是编译器会在使用 -Wshadow 时考虑阴影变量,并且它会在其他代码中混淆这些警告。

此外,在一个非平凡的构造函数中,你犯了一个错误,忘记把这个>放在成员名称前面。

Java甚至不允许这样做。这是不好的做法,应该避免。

嘿伙计们,这是一个很好的问题。如果你想为字段和构造函数参数/方法参数使用相同的名称,你必须使用范围解析(::(运算符,或者你可以使用这个(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;
        }
};