0

在定义一个类时,在自己的定义中使用成员时cls是否有必要(或良好做法)为成员添加类名前缀,还是隐式完成?例如cls::cls

class cls {
    int x;
    void foo();
    void bar();
}
void cls::foo() {
    x++;    // or use cls::x?
    bar();  // or cls::bar()?
}

如果是这样,那么创建一个类是否cls自动意味着它也是一个命名空间(因为我认为::运算符仅与命名空间一起使用)?

编辑(跟进): 如果我们不使用cls::or this->,那么如果我的源代码x在类外也有一个变量怎么办?怎么会cls::foo()知道x++指的是哪一个?

4

3 回答 3

2

用类名明确限定成员变量的使用是一个坏主意。充其量,它是不必要的(或者在必要的情况下, this->member 更好)并禁止重构(如果重命名类,可以更改更多地方),最坏的情况是它会引入错误,因为对虚函数的合格调用不会分派到覆盖的版本.

于 2013-05-10T13:13:20.483 回答
1

没有。至少不是这样。

您可以使用this->它使读者更清楚。然而::是另一回事。它用于访问静态成员变量或函数。

int x;                  // Global x
namespace ot { int x; } // another x
class cls {
    int x;              // Normal member
    static int y;       // Static member
    void foo();
    static void bar();  // Static member function
}
void cls::foo() {
    this->x++;    // Modify own x. 
    x++           // Modify own x. This has implicit this->
    ::x++;        // Modify the global x.
    ot::x++;      // Modify the x in namespace ot.
    cls::y++;     // modify the static member
    cls::bar();   // static member function. same as bar()
}
于 2013-05-10T13:10:18.277 回答
1

您上面显示的代码定义了一个类,但最初只声明成员函数(然后再定义它们)。我之所以提到这一点,是因为术语对于有效沟通很重要。

如果您内联定义类成员,则不使用范围解析运算符 ::,例如:

class cls {
    void hello() { cout << "Hello world"; }
};

如果您分别定义它们,那么您确实需要它,因为否则编译器无法确切知道您打算定义什么函数:

class cls {
    void hello();
};

void cls::hello() { cout << "Hello world"; };

一般来说,作用域解析运算符的使用不限于使用命名空间;只要需要向编译器提供完全限定的名称,就可以使用它。

在大多数情况下从类范围内访问类成员时,您可以使用它们的非限定名称;编译器将自行解决它们。因此,例如,在您的代码中,所有这些都是等效的:

x++;
cls::x++;
this->x++;
this->cls::x++; // yes, this too

每当有多个具有相同名称的成员并且编译器将非限定名称解析为您想要的成员之外的其他名称时,您都需要限定名称。例子:

void cls::foo(int x) {
    x++;       // increments the argument
    cls::x++;  // increments the member
    this->x++; // also increments the member
}

还要考虑cls可能源自base,也base可能定义 a x。在这种情况下,它的工作方式如下:

void cls::foo() {
    x++;       // increments foo::x
    cls::x++;  // increments foo::x
    base::x++; // increments base::x
}
于 2013-05-10T13:12:59.957 回答