Skip to content

Non-static member functions

Member method is a kind of function

在阅读下面文章时:

其中都有关于member method、implicit object parameter、implied object argument的讨论,并且在accu Overload Resolution - Selecting the Function中说明了这样做的原因:

This is an easy way to make the overloading rules uniform for the member functions and free functions.

显然,从实现层面来看,Member method is a kind of function,这样我们可以使用一个统一的模型来描述free function、member method。这是符合在 C++\Language-reference\Basic-concept\index.md 中提出的“Uniform function model”的。

cppreference Non-static member functions

Within the body of a non-static member function of X, any id-expression E (e.g. an identifier) that resolves to a non-type non-static member of X or of a base class of X, is transformed to a member access expression (*this).E (unless it's already a part of a member access expression). This does not occur in template definition context, so a name may have to be prefixed with this-> explicitly to become dependent.

NOTE: 关于上面这段话中的“non-type non-static member of X or of a base class of X”的理解,其实它就是表示普通的data member、member method。

关于上面这段话中的id-expression,参见C++\Language-reference\Expressions

const- and volatile-qualified member functions

Differently cv-qualified functions have different types and so may overload each other.

NOTE: CV修饰的是不同的type,关于overload,参见C++\Language-reference\Functions\Function-overload章节

In the body of a cv-qualified function, *this is cv-qualified, e.g. in a const member function, only other const member functions may be called normally. (A non-const member function may still be called if const_cast is applied or through an access path that does not involve this.)

NOTE: 这样的涉及保证了C++的type safety.

在cppreference const_cast conversion中给出了例子。

#include <vector>
#include <iostream>

struct Array
{
    std::vector<int> data;
    Array(int sz) :
            data(sz)
    {
    }
    // const member function
    int operator[](int idx) const
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        // this has type const Array*
        return data[idx]; // transformed to (*this).data[idx];
    }
    // non-const member function
    int& operator[](int idx)
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        // this has type Array*
        return data[idx]; // transformed to (*this).data[idx]
    }
};
int main()
{
    Array a(10);
    /**
     * OK: the type of a[1] is int&
     * 选择非const版本
     */
    a[1] = 1;
    const Array ca(10);
    // ca[1] = 2; // Error: the type of ca[1] is int
    /**
     * 选择const版本
     */
    ca[1];
}
// g++ --std=c++11 test.cpp

NOTE:上述程序的输出如下:

int& Array::operator[](int)
int Array::operator[](int) const

NOTE: 上述对CV-qualified member function的讨论中,仅仅涉及到了member function,但是并没有涉及到**data member**。在**const-qualified member function**,由于this是const-qualified,所以所有的data member都是const-qualified的(在member function中,所有的member access都会被转换为this->),因此在const-qualified member function中compiler会进行CV的检查,一旦违背了CV,则会报编译错误,下面是一些例子:

1) Example1: 来源: cppreference this#Example

class T
{
  int x;
  int y;
  void foo()
  {
      x = 6;       // same as this->x = 6;
      this->x = 5; // explicit use of this->
  }

  void foo() const
  {
      x = 7; // Error: *this is constant
  }
public:
  T(int x) :
                  x(x), // uses parameter x to initialize member x
                  y(this->x) // uses member x to initialize member y
  {
  }
};

int main()
{
  T t(3);
}
// g++ test.cpp

上述程序编译报错如下:

test.cpp: 在成员函数‘void T::foo() const’中:
test.cpp:13:5: 错误:assignment of member T::x in read-only object
   x = 7; // Error: *this is constant

1) Example2: 来源: 我自创的

#include <vector>
struct X
{
};

class T
{
  std::vector<X> m;
  void foo()
  {
      X &x = m[0]; // 非const,所有使用普通reference即可
  }

  void foo() const
  {
      X &x = m[0]; // const,需要使用const reference
  }

public:
  T()
  {
  }
};

int main()
{
  T t;
}
// g++ test.cpp

上述程序编译报错如下:

test.cpp: 在成员函数‘void T::foo() const’中:
test.cpp:16:13: 错误:将类型为‘X&’的引用初始化为类型为‘const X’的表达式无效
   X &x = m[0]; // const,需要使用const reference

修正版本如下:

#include <vector>
struct X
{
};

class T
{
  std::vector<X> m;
  void foo()
  {
      X &x = m[0]; // 非const,所有使用普通reference即可
  }

  void foo() const
  {
      const X &x = m[0]; // const,需要使用const reference
  }

public:
  T()
  {
  }
};

int main()
{
  T t;
}

ref-qualified member functions(since C++11)

ref-qualifier syntax overload resolution
no ref-qualifier
lvalue ref-qualifier void f() & the implicit object parameter has type lvalue reference to cv-qualified X
rvalue ref-qualifier void f() && the implicit object parameter has type rvalue reference to cv-qualified X
#include <iostream>
struct S
{
    void f() &
    {
        std::cout << "lvalue\n";
    }
    void f() &&
    {
        std::cout << "rvalue\n";
    }
};

int main()
{
    S s;
    s.f();            // prints "lvalue"
    std::move(s).f(); // prints "rvalue"
    S().f();          // prints "rvalue"
}
// g++ --std=c++11 test.cpp

qualified方式总结

qualified方式 thispointer的影响 对overload resolution的影响
const- and volatile-qualified In the body of a cv-qualified function, *this is cv-qualified CV-qualified member function是不同的function
ref-qualified ref-qualification does not change the properties of the this pointer: within a rvalue ref-qualified function, *this remains an lvalue expression. ref-qualified member functions是不同的function

Special member functions

NOTE: 这在C++\Language-reference\Classes\Special-member-functions章节进行介绍