##### cppreference.com

##### Search

Create account

##### Namespaces

- Page
- Discussion

##### Variants

##### Views

- View
- Edit
- History

##### Actions

# Non-static member functions

From cppreference.com
< cpp‎ | language

Non-static member functions are the functions that are 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-qualifie
        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 namespace

Any 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

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 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)

    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
    }

### [edit] 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 name of the function in 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 either an lvalue ref-qualifier (the character `&` after the function name) or rvalue ref-qualifier (the character `&&` after the function name. During overload resolution, non-static cv-qualified member function of class X is treated as a function that takes an implicit parameter of type lvalue reference to cv-qualified X if it has no ref-qualifiers or if it has the lvalue ref-qualifier. Otherwise (if it has rvalue ref-qualifier), it is treated as a function taking an implicit parameter of 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"
    }
Note: unlike cv-qualification, ref-qualification does not change the properties of the this pointer: within a rvalue ref-qualified function, *this remains an lvalue expression. | (since C++11)

### [edit] 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.

### [edit] Special member functions

| This section is incomplete Reason: probably needs its own page. Needs details on explicitly-defaulted/deleted defs. Needs details on non-default/non-copy constructors (e.g. converting), don't forget that in C++11, converting constructors can take more than one non-default argument

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
- Move constructor (since C++11)
- Copy assignment operator
- Move assignment operator (since C++11)
- Destructor

### [edit] Example

Run this code

    #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

### [edit] See also

- classes
- data members
- static data members

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/language/member_functions&oldid=71673"
Category:

- Todo with reason