Member Functions in C++

#include <iostream>

struct Date
{
    // here are our member variables
    int year {};
    int month {};
    int day {};
};

void print(const Date& date)
{
    // member variables accessed using member selection operator (.)
    std::cout << date.year << '/' << date.month << '/' << date.day;
}

int main()
{
    Date today { 2020, 10, 14 }; // aggregate initialize our struct

    today.day = 16; // member variables accessed using member selection operator (.)
    print(today);   // non-member function accessed using normal calling convention

    return 0;
}

Member functions

In addition to having member variables, class types (which includes structs, classes, and unions) can also have their own functions. Functions that belong to a class type are called member functions.

Functions that are not member functions are called non-member functions (or occasionally free functions) to distinguish them from member functions.

Member functions must be declared inside the class type definition, and can be defined inside or outside of the class type definition. As a reminder, a definition is also a declaration, so if we define a member function inside the class, that counts as a declaration.

A member function example

// Member function version
#include <iostream>

struct Date
{
    int year {};
    int month {};
    int day {};

    void print() // defines a member function named print
    {
        std::cout << year << '/' << month << '/' << day;
    }
};

int main()
{
    Date today { 2023, 11, 19 }; // aggregate initialize our struct

    today.day = 16; // member variables accessed using member selection operator (.)
    today.print();  // member functions also accessed using member selection operator (.)

    return 0;
}

This program compiles and produces the below result:

2023/11/19

Member functions are declared inside the class type definition

In the non-member example, the print() non-member function is defined outside of the Date struct, in the global namespace.

In the member example, the print() member function is declared inside the Date struct definition. Because print() is declared as part of the Date, this tells the compiler that print() is a member function.

Calling member functions

The member functions are called by the dot operator (.).

 

Some Things

  • Member variables and functions can be defined in any order
  • Member functions can be overloaded

Structs and member functions

In C, structs only have data members, not member functions. While C++ have both.

Member access

Each member of a class type has a property called an access level that determines who can access that member.

C++ has three different levels: public, private and protected.

Whenever a member is accessed, the compiler checks whether the access level of the member permits that member to be accessed. If the access is not permitted, the compiler will generate a compilation error. This access level system is sometimes informally called access controls.

The members of a struct are public by default

Members that have the public access level are called public members. Public members are members of a class type that do not have any restrictions on how they can be accessed. Public members can be accessed by other members of the same class, can be accessed by the public, which is what we call code that exists outside the members of a given class type. Examples of the public include non-member functions, as well as the members of other class types.

#include <iostream>

struct Date
{
    // struct members are public by default, can be accessed by anyone
    int year {};       // public by default
    int month {};      // public by default
    int day {};        // public by default

    void print() const // public by default
    {
        // public members can be accessed in member functions of the class type
        std::cout << year << '/' << month << '/' << day;
    }
};

// non-member function main is part of "the public"
int main()
{
    Date today { 2020, 10, 14 }; // aggregate initialize our struct

    // public members can be accessed by the public
    today.day = 16; // okay: the day member is public
    today.print();  // okay: the print() member function is public

    return 0;
}

The members of a class are private by default

Members that have the private access level are called private members. Private members are members of a class type that can only be accessed by other members of the same class.

#include <iostream>

class Date // now a class instead of a struct
{
    // class members are private by default, can only be accessed by other members
    int m_year {};     // private by default
    int m_month {};    // private by default
    int m_day {};      // private by default

    void print() const // private by default
    {
        // private members can be accessed in member functions
        std::cout << m_year << '/' << m_month << '/' << m_day;
    }
};

int main()
{
    Date today { 2020, 10, 14 }; // compile error: can no longer use aggregate initialization

    // private members can not be accessed by the public
    today.m_day = 16; // compile error: the m_day member is private
    today.print();    // compile error: the print() member function is private

    return 0;
}

Setting access levels via access specifiers

By default, the members of structs (and unions) are public, and the members of classes are private.

However, we can explicitly set the access level of our members by using an access specifier. An access specifier sets the access level of all members that follow the specifier. C++ provides three specifiers: public:, private:, and protected:.

class Date
{
// Any members defined here would default to private

public: // here's our public access specifier

    void print() const // public due to above public: specifier
    {
        // members can access other private members
        std::cout << m_year << '/' << m_month << '/' << m_day;
    }

private: // here's our private access specifier

    int m_year { 2020 };  // private due to above private: specifier
    int m_month { 14 }; // private due to above private: specifier
    int m_day { 10 };   // private due to above private: specifier
};

int main()
{
    Date d{};
    d.print();  // okay, main() allowed to access public members

    return 0;
}
Access levelAccess specifierMember accessDerived class accessPublic access
Publicpublic:yesyesyes
Protectedprotected:yesyesno
Privateprivate:yesnono