3

访问作为方法类的一部分的成员数据/函数的正确方法是什么?似乎有3种手段:

class test{
    private:
        int variable;
    public:
        void setVariable(int value) {
            variable = value;        // method 1, using the variable name directly
            this->variable = value;  // method 2, via pointer dereference of 'this'
            test::variable = value;  // method 3, via scope operator
        }
};

据我所知,它们似乎都有效。它们是等价的吗?除了样式/一致性之外,是否有理由使用另一种?

4

8 回答 8

3

正如您所提到的,除了样式和一致性之外,有时您还必须使用特定的语法来消除歧义。

“方法 2”可用于消除局部变量和类成员之间的歧义。

“方法 3”可用于消除类层次结构中不同位置的同名字段之间的歧义。

于 2012-11-07T18:43:36.837 回答
3

一般来说,这并不重要,因此更简单的选项member = value;是首选。在某些情况下,局部变量可能存在歧义,您可以使用this->前缀进行限定,但更好的方法是完全避免歧义。

然而,在某些极端情况下它确实很重要。在处理虚函数时,使用限定名称 ( type::member)禁用运行时调度并确保type调用该级别的最终覆盖器:

struct base {
   virtual int f() { return 1; }
};
struct derived : base {
   virtual int f() { return 2; }
   void g() {
      std::cout << f() << "\n";
      std::cout << derived::f() << "\n";
   }
};
struct mostderived : derived {
   virtual int f() { return 3; }
};
int main() {
   mostderived d;
   d.g();            // 3 2
}

在处理模板类和继承时,查找分两个阶段执行。在第一阶段,必须解析非依赖名称。非限定名称是非依赖名称,因此在某些情况下,您需要使用this->or来限定type::,并且上述区别仍然适用。额外的资格用于使名称依赖

template <typename T>
struct derived : T {
   void g() {
      // std::cout << f() << "\n";    // Error, cannot resolve f() [*]
      this->f();                      // Ok, pick final overrider at runtime 
      derived::f();                   // Ok, pick overrider here: base::f()
   }
};
struct base {
   virtual int f() { return 1; }
};
struct mostderived : derived<base> {
   virtual int f() { return 3; }
};
int main() {
   mostderived d;
   d.g();                             // 3, 1
}
于 2012-11-07T19:15:19.247 回答
1
  • 方法一:这是常见的做法。
  • 方法2:这是最好和最一致的方法。它使阅读和理解正在发生的事情变得非常清楚。
  • 方法3:我从未见过在现实世界的代码中完成过。

附带说明:当使用方法 1时,如果函数参数和成员变量存在命名冲突,则函数参数将用于成员变量。

如果我们有:

void setVariable(int variable) {
    variable = variable;        // method 1, this does not change the member variable.
    this->variable = variable;  // method 2, via pointer dereference of 'this'
    test::variable = variable;  // method 3, via scope operator
}
于 2012-11-07T18:43:30.127 回答
1

对于对象内部的代码,它通常没有区别,因此使用它variable = value;并完成它通常是最干净的。

有时在模板中,您可能会遇到仅使用变量名本身就模棱两可的情况,并this->variable消除了这种模棱两可的情况——但这非常罕见,我绝对不会定期this->everything使用,因为它可能有用一次在很长一段时间内。

于 2012-11-07T18:45:06.517 回答
0

指针 this 通常用于在类的重载运算符中进行比较。如果在函数中传递的参数与对象本身相同,则它的用途之一可能是:

class CDummy {
  public:
    int isitme (CDummy& param);
};

int CDummy::isitme (CDummy& param)
{
  if (&param == this) return true;
  else return false;
} 

也用于返回指向对象本身的指针

ClassEx ClassEx::Func(//params)
{
    //code
    return *this;
}

至于正常比较,除非您正在检查值,否则使用会更有效,value而不是更有效。this->valuethis->

于 2012-11-07T18:44:03.273 回答
0

并添加到上述答案中:一些代码样式喜欢使用固定前缀来识别成员变量,例如_or m。使用“方法 2”是在代码中实现这种清晰度的另一种(而且是更好的方法)。

Prefering this->valueovervalue也有点像使用std::cininsteadcinusing namespace std.

于 2012-11-07T19:45:49.003 回答
0

性能上没有区别。用于避免歧义,例如当::您有一个与字段同名的局部变量时,或者在派生类中声明一个与字段同名的字段的基类。支持 是因为的->类型this是指向对象的指针,因此编译器必须接受this->something,这也可用于避免歧义或只是让代码更清晰。

于 2012-11-07T18:46:55.147 回答
-1

使用方法一

variable = value;

节省您购买新键盘的频率!

(话虽如此,我应该停止在我的咖啡上加咖啡!)

于 2012-11-07T18:42:50.707 回答