Non-static member functions - cppreference.com

A non-static member function is a function that is declared in a

member specification

of a class without a

static

or

friend

specifier (see

static member functions

and

friend declaration

for the effect of those keywords).

classS{intmf1();// non-static member function declarationvoidmf2()volatile,mf3()&&;// can have cv-qualifiers and/or a reference-qualifier// the declaration above is equivalent to two separate declarations:// void mf2() volatile;// void mf3() &&;intmf4()const{returndata;}// can be defined inlinevirtualvoidmf5()final;// can be virtual, can use final/overrideS():data(12){}// constructors are member functions toointdata;};intS::mf1(){return7;}// if not defined inline, has to be defined at namespace

Constructors

,

destructors

, and

conversion functions

use special syntaxes for their declarations. The rules described in this page may not apply to these functions. See their respective pages for details.

An implicit object member function is a non-static member function without an explicit object parameter (prior to C++23, this was the only kind of non-static member function, and hence referred to as "non-static member function" in the literature).

Explanation

Any

function declarations

are allowed, with additional syntax elements that are only available for non-static member functions:

pure-specifiers

, cv-qualifiers, ref-qualifiers,

final

and

override

specifiers(since C++11), and

member initialization lists

.

A non-static member function of class X may be called

1) For an object of type X using the class member access operator

2) For an object of a class

derived

from X

3) Directly from within the body of a member function of X

4) Directly from within the body of a member function of a class derived from X

Calling a non-static member function of class X on an object that is not of type X, or of a type derived from X invokes undefined behavior.

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

.

structS{intn;voidf();};voidS::f(){n=1;// transformed to (*this).n = 1;}intmain(){Ss1,s2;s1.f();// changes s1.n}Within the body of a non-static member function of X, any unqualified-id that resolves to a static member, an enumerator or a nested type of X or of a base class of X, is transformed to the corresponding qualified-id:

structS{staticintn;voidf();};voidS::f(){n=1;// transformed to S::n = 1;}intmain(){Ss1,s2;s1.f();// changes S::n}Member functions with cv-qualifiers

An implicit object member function can be declared with a

cv-qualifier

sequence (const, volatile, or a combination of const and volatile), this sequence appears after the parameter list in the

function declaration

. Functions with different cv-qualifier sequences (or no sequence) have different types and so may overload each other.

In the body of a function with a cv-qualifier sequence, *this is cv-qualified, e.g. in a member function with const qualifier, only other member functions with const qualifier may be called normally. A member function without const qualifier may still be called if

const_cast

is applied or through an access path that does not involve

this

.

#include<vector>structArray{std::vector<int>data;Array(intsz):data(sz){}// const member functionintoperator[](intidx)const{// the this pointer has type const Array*returndata[idx];// transformed to (*this).data[idx];}// non-const member functionint&operator[](intidx){// the this pointer has type Array*returndata[idx];// transformed to (*this).data[idx]}};intmain(){Arraya(10);a[1]=1;// OK: the type of a[1] is int&constArrayca(10);ca[1]=2;// Error: the type of ca[1] is int}Member functions with ref-qualifier

An implicit object member function can be declared with no ref-qualifier, with an lvalue ref-qualifier (the token & after the parameter list) or the rvalue ref-qualifier (the token && after the parameter list). During

overload resolution

, an implicit object member function with a cv-qualifier sequence of class X is treated as follows:

no ref-qualifier: the implicit object parameter has type lvalue reference to cv-qualified X and is additionally allowed to bind rvalue implied object argument

lvalue ref-qualifier: the implicit object parameter has type lvalue reference to cv-qualified X

rvalue ref-qualifier: the implicit object parameter has type rvalue reference to cv-qualified X

#include<iostream>structS{voidf()&{std::cout<<"lvalue\n";}voidf()&&{std::cout<<"rvalue\n";}};intmain(){Ss;s.f();// prints "lvalue"std::move(s).f();// prints "rvalue"S().f();// prints "rvalue"}Note: unlike cv-qualification, ref-qualification does not change the properties of the

this

pointer: within an rvalue ref-qualified function, *this remains an lvalue expression.

(since C++11)Virtual and pure virtual functions

A non-static member function may be declared virtual or pure virtual. See

virtual functions

and

abstract classes

for details.

Explicit object member functions

A member function's first parameter can be an

explicit object parameter

(denoted with the prefixed keyword this), unless:

the function is static or virtual,

the function is declared with a cv-qualifier or ref-qualifier, or

the first parameter is a

function parameter pack

.

structX{voidfoo(thisXconst&self,inti);// same as void foo(int i) const &;// void foo(int i) const &; // Error: already declaredvoidbar(thisXself,inti);// pass object by value: makes a copy of “*this”};For member function templates, explicit object parameter allows deduction of type and value category, this language feature is called “deducing this”:

structX{template<typenameSelf>voidfoo(thisSelf&&,int);};structD:X{};voidex(X&x,D&d){x.foo(1);// Self = X&move(x).foo(2);// Self = Xd.foo(3);// Self = D&}This makes it possible to deduplicate const- and non-const member functions, see

array subscript operator

for an example.

Inside the body of an explicit object member function, the this pointer cannot be used: all member access must be done through the first parameter, like in static member functions:

structC{voidbar();voidfoo(thisCc){autox=this;// error: no thisbar();// error: no implicit this->c.bar();// ok}};A pointer to an explicit object member function is an ordinary pointer to function, not a pointer to member:

structY{intf(int,int)const&;intg(thisYconst&,int,int);};autopf=&Y::f;pf(y,1,2);// error: pointers to member functions are not callable(y.*pf)(1,2);// okstd::invoke(pf,y,1,2);// okautopg=&Y::g;pg(y,3,4);// ok(y.*pg)(3,4);// error: “pg” is not a pointer to member functionstd::invoke(pg,y,3,4);// ok(since C++23)Special member functions

Some member functions are special: under certain circumstances they are defined by the compiler even if not defined by the user. They are:

Default constructor

Copy constructor

Copy assignment operator

Destructor

(until C++20)

Prospective destructor

(since C++20)

Special member functions along with the

comparison operators

(since C++20) and postfix increment or decrement operators(since C++29) are the only functions that can be defaulted, that is, defined using =default instead of the function body (see their pages for details).

Notes

Feature-test macro ValueStdFeature

__cpp_ref_qualifiers

200710L

(C++11)

ref-qualifiers

__cpp_explicit_this_parameter

202110L

(C++23)

explicit object parameter

(

deducing this

) Example

Run this code

#include<exception>#include<iostream>#include<string>#include<utility>structS{intdata;// simple converting constructor (declaration)S(intval);// simple explicit constructor (declaration)explicitS(std::stringstr);// const member function (definition)virtualintgetData()const{returndata;}};// definition of the constructorS::S(intval):data(val){std::cout<<"ctor1 called, data = "<<data<<'\n';}// this constructor has a catch clauseS::S(std::stringstr)try:data(std::stoi(str)){std::cout<<"ctor2 called, data = "<<data<<'\n';}catch(conststd::exception&){std::cout<<"ctor2 failed, string was '"<<str<<"'\n";throw;// ctor's catch clause should always rethrow}structD:S{intdata2;// constructor with a default argumentD(intv1,intv2=11):S(v1),data2(v2){}// virtual member functionintgetData()constoverride{returndata*data2;}// lvalue-only assignment operatorD&operator=(Dother)&{std::swap(other.data,data);std::swap(other.data2,data2);return*this;}};intmain(){Dd1=1;Ss2("2");try{Ss3("not a number");}catch(conststd::exception&){}std::cout<<s2.getData()<<'\n';Dd2(3,4);d2=d1;// OK: assignment to lvalue// D(5) = d1; // ERROR: no suitable overload of operator=}Output:

ctor1 called, data = 1 ctor2 called, data = 2 ctor2 failed, string was 'not a number' 2 ctor1 called, data = 3 Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior

CWG 194

C++98 ambiguous whether a non-static member function
could have the same name as the enclosing class name explicit naming restriction added See also

classes

non-static data members

static data members