构造函数初始化列表中的“this”指针

27

我想我无法理解为什么这不起作用。我一直以为可以在构造函数中使用'this'指针,但我从未知道不能在初始化列表中使用'this'。

#include <iostream>

class A {
    public:
        int a;
        int b;
        A(int a = 0, int b = 0) : this->a(a), this->b(b) { }
        void print() {
        std::cout << a << ", " << b << std::endl;
    }
};

int main() {
    A a;
    a.print();
}

我对与此相关的细节感兴趣。


我已经打上了“语言律师”的标签:我并不确定我的答案是否正确。 - Bathsheba
3
你并不在构造函数的内部,而是在构造函数的初始化列表中。 - David Schwartz
2
@DavidSchwartz b(this->a) 就可以了。 - Potatoswatter
非常感谢您的问题!节省了我的时间! - Sam
2个回答

36

因为没有必要,初始化列表已经可以消除歧义,因为其语法是严格的:

member(value)

那么你只需要将它改成:

A(int a = 0, int b = 0) : a(a), b(b) {}

this->member 只有在程序员需要帮助编译器消除歧义时才会真正使用,例如,如果您的构造函数看起来像:


A(int a = 0, int b = 0) 
{ 
  // set local 'a' to itself
  a = a; 
}

你的A::a现在还没有被初始化,糟糕!

你需要使用this来帮助编译器:

A(int a = 0, int b = 0) 
{ 
  this->a = a; // set A::a to local a.
}

我想补充一点,在 C++ 中,当存在歧义时使用 this 访问成员更多的是 Java 的用法。在 C++ 中,您的属性应该(通常)有一个类似 a_ 的名称,这将上面的代码简化为 a_ = a;。引用 Google C++ Style Guide 的话说:类的数据成员(但不包括结构体)应该添加下划线后缀。 - Konstantin
13
请注意,Google C++风格指南在C++程序员中并不受好评,不应被视为代表C++社区推荐的内容。 - ruakh
@KonstantinĐ。前缀/后缀命名约定的价值非常主观,而且通常是不必要的。这就是为什么this构造存在的原因。我建议阅读Bob Martin的《Clean Code》以获得不同的视角。 - drognisep

30

this->a在语法上是无效的,因为它是一个成员访问表达式,但只允许使用标识符(或基类的类型说明符)。

根据C++标准[class.base.init]的规定:

mem-initializer-id:
      class-or-decltype
      identifier


5
好的,"why"是因为没有必要为了添加 this-> 而使语法变得更加复杂。实际上,你会需要使用一堆 "...不符合规范" 的规则来禁止你刚刚添加的任何东西,除了添加的 this-> 之外。 - Lightness Races in Orbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接