Non-static member functions
A non-static member function is a function that is declared in a member specification of a class without a static or friend specifier.
class S {
int mf1(); // non-static member function declaration
void mf2() volatile, mf3() &&; // can be cv-qualified and reference-qualified
int mf4() const { return data; } // can be defined inline
virtual void mf5() final; // can be virtual, can use final/override
S() : data(12) {} // constructors are member functions too
int data;
};
int S::mf1() { return 7; } // if not defined inline, has to be defined at namespaceAny function declarations are allowed, with additional syntax elements that are only available for non-static member functions: final and override specifiers, pure-specifiers, cv-qualifiers, ref-qualifiers, and member initialization lists.
A non-static member function of class X may be called.
Calling a member function of class X on an object of any other type 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.
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 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.
struct S {
static int n;
void f();
};
void S::f() {
n = 1; // transformed to S::n = 1;
}
int main() {
S s1, s2;
s1.f(); // changes S::n
}const-, volatile-, and ref-qualified member functions
A non-static member function can be declared with a const, volatile, or const volatile qualifier (this qualifier appears after the parameter list in the function declaration). Differently cv-qualified functions have different types and so may overload each other.
In the body of a cv-qualified function, the this pointer 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.).
#include <vector>
struct Array {
std::vector<int> data;
Array(int sz) : data(sz) {}
// const member function
int operator[](int idx) const {
// this has type const Array*
return data[idx]; // transformed to (*this).data[idx];
}
// non-const member function
int& operator[](int idx) {
// this 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
}| A non-static member function can be declared with no ref-qualifier, with an lvalue ref-qualifier (the token
#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"
}Note: unlike cv-qualification, ref-qualification does not change the properties of the this pointer: within a rvalue ref-qualified function, | (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.
Special member functions
constructors and destructors are non-static member functions that use a special syntax for their declarations (see their pages for details).
Some member functions are special: 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 functions along with the comparison operators (since C++20) are the only functions that can be defaulted, that is, defined using = default instead of the function body (see their pages for details).
Example
#include <iostream>
#include <string>
#include <utility>
#include <exception>
struct S {
int data;
// simple converting constructor (declaration)
S(int val);
// simple explicit constructor (declaration)
explicit S(std::string str);
// const member function (definition)
virtual int getData() const { return data; }
};
// definition of the constructor
S::S(int val) : data(val) {
std::cout << "ctor1 called, data = " << data << '\n';
}
// this constructor has a catch clause
S::S(std::string str) try : data(std::stoi(str)) {
std::cout << "ctor2 called, data = " << data << '\n';
} catch(const std::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 function
int 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(const std::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 = 1 ctor2 called, data = 2 ctor2 failed, string was 'not a number' 2 ctor1 called, data = 3
See also
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/language/member_functions