General topics | ||||||||||||||||
Flow control | ||||||||||||||||
Conditional execution statements | ||||||||||||||||
Iteration statements (loops) | ||||||||||||||||
Jump statements | ||||||||||||||||
Functions | ||||||||||||||||
Function declaration | ||||||||||||||||
Lambda function expression | ||||||||||||||||
inline specifier | ||||||||||||||||
Dynamic exception specifications(until C++17*) | ||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||
Exceptions | ||||||||||||||||
Namespaces | ||||||||||||||||
Types | ||||||||||||||||
Specifiers | ||||||||||||||||
| ||||||||||||||||
Storage duration specifiers | ||||||||||||||||
Initialization | ||||||||||||||||
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
A non-static member function is a function that is declared in amember specification of a class without astatic
orfriend
specifier(seestatic member functions andfriend declaration for the effect of those keywords).
class S{int mf1();// non-static member function declarationvoid mf2()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() &&; int mf4()const{return data;}// can be defined inlinevirtualvoid mf5() final;// can be virtual, can use final/override S(): data(12){}// constructors are member functions tooint data;}; int S::mf1(){return7;}// if not defined inline, has to be defined at namespace
Constructors,destructors, andconversion 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.
Anexplicit object member function is a non-static member function with anexplicit object parameter. | (since C++23) |
Animplicit 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).
Contents |
Anyfunction declarations are allowed, with additional syntax elements that are only available for non-static member functions:pure-specifiers, cv-qualifiers, ref-qualifiers,final
andoverride
specifiers(since C++11), andmember initialization lists.
A non-static member function of classX
may be called
X
using the class member access operatorX
X
Calling a non-static member function of classX
on an object that is not of typeX
, or of a type derived fromX
invokes undefined behavior.
Within the body of a non-static member function ofX
, anyid-expressione (e.g. an identifier) that resolves to a non-type non-static member ofX
or of a base class ofX
, 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 withthis-> explicitly to becomedependent.
struct S{int n;void f();}; void S::f(){ n=1;// transformed to (*this).n = 1;} int main(){ S s1, s2; s1.f();// changes s1.n}
Within the body of a non-static member function ofX
, any unqualified-id that resolves to a static member, an enumerator or a nested type ofX
or of a base class ofX
, is transformed to the corresponding qualified-id:
struct S{staticint n;void f();}; void S::f(){ n=1;// transformed to S::n = 1;} int main(){ S s1, s2; s1.f();// changes S::n}
An implicit object member function can be declared with acv-qualifier sequence (const,volatile, or a combination ofconst andvolatile), this sequence appears after the parameter list in thefunction 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 withconst qualifier, only other member functions withconst qualifier may be called normally. A member function withoutconst qualifier may still be called ifconst_cast
is applied or through an access path that does not involvethis
.
#include <vector> struct Array{std::vector<int> data; Array(int sz): data(sz){} // const member functionint operator[](int idx)const{// the this pointer has type const Array*return data[idx];// transformed to (*this).data[idx];} // non-const member functionint& operator[](int idx){// the this pointer has type Array*return data[idx];// transformed to (*this).data[idx]}}; int main(){ Array a(10); a[1]=1;// OK: the type of a[1] is int&const Array ca(10); ca[1]=2;// Error: the type of ca[1] is int}
Member functions with ref-qualifierAn implicit object member function can be declared with no ref-qualifier, with an lvalue ref-qualifier (the token
Note: unlike cv-qualification, ref-qualification does not change the properties of the | (since C++11) |
A non-static member function may be declaredvirtual orpure virtual. Seevirtual functions andabstract classes for details.
Explicit object member functionsFor a non-static non-virtual member function not declared with cv-qualifier or ref-qualifier, its first parameter, if not being afunction parameter pack, can be anexplicit object parameter (denoted with the prefixed keywordthis): struct X{void foo(this Xconst& self,int i);// same as void foo(int i) const &;// void foo(int i) const &; // Error: already declared void bar(this X self,int i);// 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 “deducingthis”: struct X{template<typename Self>void foo(this Self&&,int);}; struct D: X{}; void ex(X& x, D& d){ x.foo(1);// Self = X& move(x).foo(2);// Self = X d.foo(3);// Self = D&} This makes it possible to deduplicate const- and non-const member functions, seearray subscript operator for an example. Inside the body of an explicit object member function, thethis pointer cannot be used: all member access must be done through the first parameter, like in static member functions: struct C{void bar(); void foo(this C c){auto x= this;// error: no this bar();// 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: struct Y{int f(int,int)const&;int g(this Yconst&,int,int);}; auto pf=&Y::f;pf(y,1,2);// error: pointers to member functions are not callable(y.*pf)(1,2);// okstd::invoke(pf, y,1,2);// ok auto pg=&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) |
Some member functions arespecial: under certain circumstances they are defined by the compiler even if not defined by the user. They are:
(since C++11) |
(since C++11) |
Special member functionsalong with thecomparison operators(since C++20) are the only functions that can bedefaulted, that is, defined using=default instead of the function body (see their pages for details).
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_ref_qualifiers | 200710L | (C++11) | ref-qualifiers |
__cpp_explicit_this_parameter | 202110L | (C++23) | explicit object parameter (deducingthis ) |
#include <exception>#include <iostream>#include <string>#include <utility> struct S{int data; // simple converting constructor (declaration) S(int val); // simple explicit constructor (declaration)explicit S(std::string str); // const member function (definition)virtualint getData()const{return data;}}; // definition of the constructorS::S(int val): data(val){std::cout<<"ctor1 called, data = "<< data<<'\n';} // this constructor has a catch clauseS::S(std::string str)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} struct D: S{int data2;// constructor with a default argument D(int v1,int v2=11): S(v1), data2(v2){} // virtual member functionint getData()const override{return data* data2;} // lvalue-only assignment operator D& operator=(D other)&{std::swap(other.data, data);std::swap(other.data2, data2);return*this;}}; int main(){ D d1=1; S s2("2"); try{ S s3("not a number");}catch(conststd::exception&){} std::cout<< s2.getData()<<'\n'; D d2(3,4); d2= d1;// OK: assignment to lvalue// D(5) = d1; // ERROR: no suitable overload of operator=}
Output:
ctor1 called, data = 1ctor2 called, data = 2ctor2 failed, string was 'not a number'2ctor1 called, data = 3
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 |