【问题标题】:Can I use identical names for fields and constructor parameters?我可以为字段和构造函数参数使用相同的名称吗?
【发布时间】:2010-09-21 01:56:42
【问题描述】:

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

合法吗?

【问题讨论】:

  • 那个';'是怎么回事?!?
  • 只是一句空话,不会有坏处的,我保证:)
  • 仅仅因为它是合法的并不意味着它是正确的; )
  • 如果你在构造函数中改变a,比如if (a < 0) a = 0;,那么你必须使用this->a

标签: c++ parameters constructor


【解决方案1】:

是的,它是合法的,适用于所有平台。 它将正确地将您的成员变量 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。

【讨论】:

  • 这是一个品味问题。我更喜欢给相同的东西起相同的名字。这就是我广泛使用命名空间的原因。
  • 对于私有字段,您经常会发现命名为“a_”或“_a”。
  • 成员变量通常是 m_a 或 a。作用域变量通常是一个.
  • 我最近也转而使用这种技术(并在方法主体中使用 this-> 消除歧义)。这是我在 C# 中的首选方式,回到 C++,我已经放弃了使用 m_ 前缀作为成员变量的旧做法。现在好多了(YMMV)
  • 关于旁注一:编译器会告诉我未使用的参数。
【解决方案2】:

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

MyClass(int a) : a(a)
{
}

但是上面的代码和这个效果一样吗?

MyClass(int a)
{
    a=a;
}

答案是否定的。每当您在构造函数的主体中键入“a”时,编译器将首先查找名为“a”的局部变量或构造函数参数,只有当它没有找到时,它才会开始寻找名为“a”的类成员(如果没有可用的,那么它将寻找一个名为“a”的全局变量,顺便说一句)。结果是上述语句“a=a”会将存储在参数“a”中的值分配给参数“a”,使其成为无用的语句。

为了将参数的值分配给类成员“a”,您需要通知编译器您正在引用 this 类实例中的值:

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

【讨论】:

    【解决方案3】:

    如果形参和成员的名字相同,那么要小心在构造函数中使用这个指针来使用成员变量

    class C {
      T a;
    public:
      C(T a): a(a) {
    this->a.sort ;//correct
    a.sort();//will not affect the actual member variable
    }
    };
    

    【讨论】:

    • 嗯……这似乎是给它们取不同名字的绝佳理由。好点。
    • 这是使用const 在函数实现中保持按值输入参数不变的一个很好的理由。
    【解决方案4】:

    合法:是的,正如 Brian 所解释的,编译器知道在初始化列表中期望的名称必须是成员(或基类),而不是其他任何东西。

    好的风格:很可能不是——对于很多程序员(包括你,似乎)结果并不明显。为参数使用不同的名称将保持代码合法并同时使其成为良好的样式。

    我更喜欢写一些:

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

    【讨论】:

    • 不,对我来说结果是显而易见的。如果 a(a) 构造是合法的,那么它肯定意味着那些 'a' 是不同的。我只是不确定它在 C++ 中是否真的合法。
    • 您需要非常小心使用带有前导下划线的标识符,以避免与实现发生冲突。当它后面跟着一个小写字符时,你实际上没问题,就像这里一样,但人们普遍认为最好完全避免它们。有关更多信息,请参阅问题 228783。
    • 这是一个偏好问题,两种方式都有好处。
    • @SergeySkoblikov 这不是很明显:a=a 也是合法的,但这并不意味着 LHS 和 RHS 有不同的含义。
    【解决方案5】:

    这种做法的问题,虽然可能是合法的,但编译器会在使用 -Wshadow 时考虑隐藏的变量,它会在其他代码中混淆这些警告。

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

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

    【讨论】:

    • Java 允许使用 this 来区分参数和字段:this.a = a;
    【解决方案6】:

    大家好,这是一个很好的问题。如果您想为字段和构造函数参数/方法参数使用相同的名称,您必须使用范围解析 (::) 运算符,或者您可以使用此 (this-&gt;) 将参数值映射到这样的成员,请检查代码 sn -p 仔细你可以很容易理解。

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

    【讨论】:

      猜你喜欢
      • 2021-09-21
      • 2015-04-20
      • 2011-12-27
      • 1970-01-01
      • 2021-11-06
      • 1970-01-01
      • 2017-03-01
      • 1970-01-01
      • 2017-11-01
      相关资源
      最近更新 更多