`* this`在成员函数体外?

时间:2013-05-13 14:05:11

标签: c++ c++11

在C ++标准的5.1.1 / 3中[expr.prim.general]

  

与其他上下文中的对象表达式不同,*为了达到目的,这不需要是完整类型   成员函数体外部的类成员访问权限。只有先前声明的班级成员   声明是可见的。

然后这个例子:

struct A {
    char g();
    template<class T> auto f(T t) -> decltype(t + g()) 
    { return t + g(); }
};
template auto A::f(int t) -> decltype(t + g());

你能解释一下这个引用和例子吗?究竟在这里展示了什么?

3 个答案:

答案 0 :(得分:6)

  

这究竟是什么样的?在这里演示哪种陈述?

正在证明的陈述是:

  

与其他上下文中的对象表达式不同,*为了达到目的,这不需要是完整类型   成员函数体外的类成员访问权限(5.2.5)。

在成员函数的主体之外,有一个g()的调用,这意味着this->g()。在那里,*this(即A)的类型不完整。

根据C ++ 11标准的第9.2 / 2段:

  

类说明符的结束},类被视为完全定义的对象类型(3.9)(或完整类型)。   在类 member-specification 中,该类在函数体内被视为完整,   默认参数和非静态数据成员的括号或等号初始化程序(包括此类内容)   嵌套类)。否则,它在其自己的类 member-specification 中被视为不完整。

答案 1 :(得分:4)

这意味着您可以在类定义中的函数体外部通过this显式或隐式地访问成员。此时,类型不完整,通常您无法访问不完整类型的成员。

但是你只能在成员函数声明的限制部分内做到这一点;关于this

的上一句话
  

它不会出现在可选的 cv-qualifier-seq

之前

意味着您不能在参数或前导返回类型规范中使用它。据我所知,在函数体外部,唯一可以使用它的地方是尾随返回类型。

在尾随返回类型中使用decltype时,可能需要执行此操作,以获取涉及非静态成员的表达式类型。该示例通过隐式使用this来访问尾随返回类型中的g()来演示这一点。如果它被写成decltype(t + this->g()),那将会更清楚地展示什么。

答案 2 :(得分:2)

首先,编译器会转换所有成员访问表达式:

struct X{
  int a;
  void f(){}
  void g(int b){
    int x = a + b; // actually: int x = (*this).a + b
    f(); // actually: (*this).f();
  }
};

§9.3.1 [class.mfct.non-static] p3

  

[...]使用(*this)(9.3.2)将 id-expression 转换为类成员访问表达式(5.2.5)作为后缀 - 表达式位于.运算符的左侧。 [...]

现在,标准中的示例在trailing-return-type中调用另一个成员函数体外的成员函数。那个电话也改变了:

template<class T> auto f(T t) -> decltype(t + (*this).g()) 
{ return t + (*this).g(); }

在成员函数体之外,*this显然是不完整的类型。这意味着您只能访问在使用之前声明的名称 - 但该部分不仅适用于*this用法:

struct X{
  using typeA = int;
  typeA f(); // OK, 'typeA' has been declared before

  typeB g(); // Error: 'typeB' not declared before usage
  using typeB = float;
};