A non-static member function is a function that is declared in a
of a class without a
or
specifier (see
and
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
,
, and
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
are allowed, with additional syntax elements that are only available for non-static member functions:
, cv-qualifiers, ref-qualifiers,
and
specifiers(since C++11), and
.
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
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
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
.
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
sequence (const, volatile, or a combination of const and volatile), this sequence appears after the parameter list in the
. 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
is applied or through an access path that does not involve
.
#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
, 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
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
and
for details.
Explicit object member functions
A member function's first parameter can be an
(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
.
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
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:
(until C++20)
(since C++20)
Special member functions along with the
(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
(C++11)
(C++23)
(
) 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
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