在C ++中过度使用`this`

时间:2009-06-29 09:35:45

标签: c++ refactoring this

我正在处理一个在整个

中使用以下构造的大型代码库
class MyClass
{
public:
  void f(int x);
private:
  int x;
};


void MyClass::f(int x)
{
'
'
  this->x = x;
'
'
}

就个人而言,我总是使用,因此更喜欢表格

class MyClass
{
public:
  void f(int x);
private:
  int _x;
};


void MyClass::f(int x)
{
'
'
  _x = x;
'
'
}

我更喜欢后者的原因是它更简洁(更少的代码=更少的潜在错误),并且我不喜欢在范围内同时拥有多个同名的变量,我可以避免它。也就是说,我现在越来越多地看到以前的用法。我不知道第二种方法有什么好处吗? (例如,对编译时的影响,使用模板化代码等等)两种方法的优点是否足够值得另一方面的重构?我问的原因是,虽然我不喜欢代码中存在的第二种方法,但是引入更多错误的工作量和相关风险并不值得重构。

15 个答案:

答案 0 :(得分:27)

你的版本有点干净,但是当你在它的时候,我会:

  1. 避免使用下划线:_x是正常的,直到有人选择_MyField这是一个保留名称。不允许使用大写字母后跟大写字母作为变量名称。请参阅:What are the rules about using an underscore in a C++ identifier?
  2. 将属性设为私有或受保护:如果进行编译,则更改是安全的,并且您将确保使用您的setter。
  3. 这个 - >故事有一个用途,例如在模板化代码中使字段名称取决于您的类型(可以解决一些查找问题)。
  4. 名称解析的一个小例子,通过使用明确的this->来解决。 (用g ++ 3.4.3测试):

    #include <iostream>
    #include <ostream>
    
    class A
    {
    public:
      int g_;
      A() : g_(1) {}
      const char* f() { return __FUNCTION__; }
    };
    
    const char* f() { return __FUNCTION__; }
    int g_ = -1;
    
    template < typename Base >
    struct Derived : public Base
    {
      void print_conflicts()
      {
        std::cout << f() << std::endl; // Calls ::f()
        std::cout << this->f() << std::endl; // Calls A::f()
        std::cout << g_ << std::endl; // Prints global g_
        std::cout << this->g_ << std::endl; // Prints A::g_
      }
    };
    
    int main(int argc, char* argv[])
    {
       Derived< A >().print_conflicts();
       return EXIT_SUCCESS;
    }
    

答案 1 :(得分:10)

字段命名与codemell无关。正如Neil所述,字段可见性是这里唯一的代码。

有关C ++中命名约定的各种文章:

答案 2 :(得分:3)

Microsoft C#编码标准鼓励使用'this'。它提供了良好的代码清晰度,旨在成为m_或_或成员变量中任何其他内容的标准。

老实说,我真的不喜欢名字中的下划线,我常常用我的所有成员加上一个'm'。

答案 3 :(得分:3)

很多人都使用它,因为在他们的IDE中会弹出当前类的标识符列表。

我知道我在BCB做过。

我认为您提供的命名冲突示例是一个例外。但是在Delphi中,样式指南使用参数前缀(通常是“a”)来避免这种情况。

答案 4 :(得分:3)

我个人的感觉是,打击现有的编码约定是你不应该做的事情。正如Sutter / Alexandrescu在他们的书“C ++编码惯例”中所说的那样:不要为这些小东西烦恼。任何人都可以阅读其中一个,是否有领先的'this-&gt;'或'_'或其他。

但是,命名约定的一致性是您通常需要的,因此在某个范围(至少是文件范围,当然理想情况下是整个代码库)中坚持一个约定被认为是一种良好的做法。你提到这个样式在更大的代码库中使用,所以我认为改进另一个约定会是一个坏主意。

毕竟,如果您发现有更改它的理由,请不要手动执行。在最好的情况下,您的IDE支持这种“重构”。否则,编写一个脚本来更改它。搜索&amp;替换应该是最后一个选项。在任何情况下,您都应该有备份(源代码管理)和某种自动化测试工具。否则你就不会玩得开心。

答案 5 :(得分:2)

以这种方式使用'this'是IMO不是代码气味,而只是个人偏好。因此,它与系统中其余代码的一致性不那么重要。如果此代码不一致,您可以将其更改为与其他代码匹配。如果通过更改它会导致与其余大部分代码不一致,这非常糟糕,我会不管它。

你不想进入打代码网球的位置,在那里有人改变某些东西纯粹是为了让它看起来“好看”,只为其他人带来不同的口味,然后将其改回来。

答案 6 :(得分:1)

我总是使用 m _ 命名约定。虽然我一般不喜欢“匈牙利符号”,但我发现如果我正在使用班级成员数据,我会非常有用。另外,我发现在同一范围内使用2个相同的变量名也容易出错。

答案 7 :(得分:0)

我同意。我不喜欢这种命名约定 - 我更喜欢在成员变量和局部变量之间存在明显区别的情况。如果你离开this会怎样?

答案 8 :(得分:0)


class MyClass{
public:  
  int x;  
  void f(int xval);
};
//
void MyClass::f(int xval){  
  x = xval;
}

答案 9 :(得分:0)

在我看来这个往往会给代码增加混乱,所以我倾向于使用不同的变量名(取决于约定,它可能是下划线, m _ ,无论如何)。

答案 10 :(得分:0)

<击> 在C ++中,使用初始化器构建初始化成员更为正常。

为此,您必须使用与成员变量名称不同的名称。

所以即使我在Java中使用Foo(int x) { this.x = x; },我也不会在C ++中使用。

真正的气味可能是缺少初始化程序和方法,除了改变成员变量之外什么都不做,而不是使用this -> x本身。

<击>

任何人都知道为什么在我使用初始化器时,我在每个C ++商店中使用不同的名称作为成员变量的构造函数参数?有些C ++编译器不支持吗?

答案 11 :(得分:0)

class MyClass
{
public:
  int m_x;
  void f(int p_x);
};


void MyClass::f(int p_x)
{
  m_x = p_x;
}

...是我使用范围前缀的首选方式。 m_表示成员,p_表示参数(有些使用a_表示参数),g_表示全局,有时l_表示本地,如果它有助于可读性。

如果你有两个值得同名的变量,那么这可以帮助很多,并且避免为了避免重新定义而必须在其意义上弥补一些随机变化。或者更糟糕的是,可怕的'x2,x3,x4等'......

答案 12 :(得分:0)

今天,大多数IDE编辑器为变量着色以指示局部变量的类成员。因此,IMO既不是前缀,也不是'this-&gt;'应该是可读性要求。

答案 13 :(得分:-1)

我不喜欢使用“这个”,因为它是原始的。如果您使用旧的C编程(记住C?),并且想要模仿OOP的某些特性,则可以创建一个包含多个成员的结构(这些类似于对象的属性)并创建一个集合所有函数都将指向该结构的指针作为它们的第一个参数(这些类似于该对象的方法)。

(我认为这种typedef语法是正确的,但已经有一段时间......)

typedef struct _myclass
{
   int _x;
} MyClass;

void f(MyClass this, int x)
{
   this->_x = x;
}

事实上,我相信较旧的C ++编译器实际上会将您的代码编译为上述形式,然后将其传递给C编译器。换句话说 - C ++在某种程度上只是语法糖。所以我不确定为什么有人会想用C ++编程并回到代码中明确使用“this” - 也许它是“语法Nutrisweet”

答案 14 :(得分:-2)

如果您对命名约定有疑问,可以尝试使用类似下面的内容。

class tea
{
public:
    int cup;
    int spoon;
    tea(int cups, int spoons);
};

class tea
{
public:
    int cup;
    int spoon;
    tea(int drink, int sugar);
};

我认为你明白了。它基本上将变量命名为不同但逻辑意义上的“相同”。我希望它有所帮助。