C++ - C++ class function - C++ class method - Programming Languages

C++ Class Methods Explained

Classes and their member functions (or methods) are integral features of the object-oriented C++ programming language. By tying these functions to an object’s namespace, class methods make your C++ code modular and reusable.

In this tutorial, we’ll start by simply calling a member function before writing our own classes and passing on their members through a technique known as “inheritance.” 

Illustrative examples along the way will help you grasp these concepts as they apply to C++ methods.

What Are Class Methods in C++?

Classes serve as blueprints for objects —  they’re at the heart of object-oriented programming (OOP). When you study an OOP language like C++, you’ll quickly learn that an object is a complex data structure with specific attributes and behavior that are respectively modeled by data members and member functions. 

Members are defined within the scope of a class:

class Cat {
 public:
 void talks() {
 // this is where we'll define the function

      }
}

Therefore, they belong to that class and may be accessed using the class’s interface through the member selection operator. 

Here’s how we would call the function talks() that we defined within the namespace of the Cat class:

Cat myCat
myCat.talks()

Crucially, this is very different from simply inputting:

talks()

Since we didn’t specify myCat as our interface, the above command would prompt the compiler to look for a free function by the name talks()

Functions that are bound to a class are commonly known as “member functions” in C++. However, in other object-oriented languages “method” is a commonly used term to distinguish them from free functions. In C++, only virtual member functions go by the name “method.” So in this blog post, we’ll stick to general convention and use the term “member function.” 

Working With Member Functions in C++

The idea behind the object-oriented paradigm is that when we write our programs in terms of objects that interact with each other, we better approximate life in the real world. To illustrate how the various members of a class serve to mimic a real-world object’s attributes and behavior, let’s go back to our Cat class. We’ll add a character variable and expand the talks() member function, which will allow our furry friend to introduce itself:

class Cat {
 std::string character = "moody";
 public:
     void talks() {
         std::cout << "Purr purr, I'm a " << character << " cat.\n";
     }
};

Let’s instantiate an object of the Cat class and call its talks() member function:

Cat myCat;
myCat.talks();

Output:

Purr purr, I'm a moody cat. 

You might have noted that we’ve been using the “public” keyword in our class definitions. Public functions are those that can be accessed from outside the class by way of the dot notation. 

If you try commenting out the “public” keyword, you’ll see an error:

error: 'void Cat::talks()' is private

This is because members are private by default. Alternatively, they can also be explicitly declared “private.” In our example, we did not want to access the character attribute from outside of the class, but merely used it within the class as part of our talks() function. 

Inheritance in C++

Perhaps you’re allergic to cats, or maybe you simply do not get along with them. Does this mean that you cannot have any other kind of pet? Of course not! We’ll use the concept of inheritance to generate many different types of pets.

Inheritance makes use of the fact that objects in the real world are often defined through their relationships with other objects. For example, a cat may be seen as a subclass of a general class of pets. Let’s first define such a class, with features and member functions common to all pets:

class Pet {
    public:
    std::string character = "sweet"; // sweetness lies in the eye of the        

                                        pet-holder
    void talks () {
        std::cout << "I'm a " << character << " pet!\n";
    };
};

Note that we’ve now defined all class members as “public.” That’s because only public or protected members can be inherited. Private members won’t be accessible by the inheriting class.

If we now want to define different types of pet classes, say for cats and frogs, we simply let them inherit features from our base Pet class. As you can see, inheritance not only lets us model relationships between animals in a realistic way, but saves us time, seeing as we no longer need to redefine all pet-specific elements each time we instantiate a new object of Pet.

class Frog: public Pet {
     }
};

Though there’s not much going on in the definition of this Frog class, specifying it as a child of Pet means that it will inherit that class’s behavior:

Frog myFrog;
myFrog.talks();

Output:

I'm a sweet pet!

Now, this is a pretty generic greeting. What if we wanted something more frog-specific, just like in the example of the Cat class above? Simple! By redefining the talks() function in the child class, we override the definition in the parent class:

...
public:
 void talks() {
 std::cout << "Quack quack, I'm a " << character " << frog.\n";
}
...

Calling myFrog.talks() on an object of the modified Frog class, we get:

Quack quack, I'm a sweet frog.

Inheritance can span multiple generations. For instance, Pet could easily have a parent class that we might call Animal that would pass its public member functions and variables on to its grandchildren and great-grandchildren. 

Readability depends not only on your programs being modular; length is also an important factor. If you’ve ever had to read someone else’s C++ code, then you probably know that the longer a class definition, the more confusing it will be. Luckily, C++ has a trick that helps programmers write shorter, more readable code: We can declare and define our class members separately. 

Declaration vs. Definition

Not only does C++ allow you to separate the declaration of a class member from its definition. In fact, it’s often seen as good practice to place the two in different files. So what’s the difference between a declaration and a definition? 

A declaration simply “announces” the existence of a variable — a member function in our case. It specifies the object type and the variable name of our function. 

However, when we define a function, we tell the compiler exactly how that function behaves. In the examples above, we always did both actions simultaneously. But, we could have just as easily separated declaration from definition, like so:

class Cat {
 public:
     void talks();
};

void Cat::talks() {
 std::cout << "Purr purr, pet me!\n";
};

In this example, we’ve quite literally defined our talks() function outside of its class. To preserve the member relationship, we used the scope resolution operator : : . This operator signals that talks() is defined within the Cat namespace.

The purpose of separating declaration from definition is to keep programs reasonably short and readable. When you actually start programming in C++, you’ll see that having all the information in one place can cause confusion and impact reusability. Therefore, many seasoned C++ programmers put their definitions in special header files (marked by the .h file extension).

A Special Member Function: The Constructor

The constructor is a function that initializes new objects. It forms part of every class — so how come we’re just now hearing about it? That’s because when the constructor is parameter-less (i.e., takes no arguments), it does not have to be explicitly defined. It’s for this reason that the constructor belongs to the class of “special member functions” in C++.

When the objects of a class are initialized with arguments, that has to be explicitly defined in what’s known as a “parameterized constructor.” A constructor goes by the same name as the class itself and has no return type. 

Let’s say that we want to pass a name to the objects of the Pet class when we initialize them:

class Pet {
    public:
        std::string myname;
        Pet (std::string name) {
            myname = name;
        };
        void talks() {
            std::cout << "Hi, I'm " << myname << ", your friendly pet!\n";
        };
};

We now need to pass a name argument to our object during initialization:

Pet myPet("Teto");
myPet.talks();

Output:

Hi, I'm Teto, your friendly pet!

If we omit the argument during initialization, the script won’t compile. To avoid this behavior, we may provide a default argument for the constructor onto which to fall back:

...
        Pet (std::string name="Totoro") {
...

We can now initialize our myPet object without any arguments:

Pet myPet;
myPet.talks();

Output:

Hi, I'm Totoro, your friendly pet!

The default argument is easily overwritten by initializing the object with a different name argument, as we did earlier with “Teto.”

Become a C++ Programmer

Working with classes and their member functions might well be the most important skill for an object-oriented programmer. 

Want to keep sharpening your C++ skills? 

Our specialized C++ nanodegree actually teaches you how to build classes, interfaces and generic templates to create an object-oriented C++ program.

Enroll in our online C++ Nanodegree today!