Learning materials

Objects and Classes in C++

On this page

Concepts

General Object-oriented Programming

  • object: a collection of coherent states and behaviors
  • class: a template of a group of similar objects
  • state: data, property, attribute, member variable
  • behavior: method, member function

map to C++ concepts

  • class: a type
  • object: a variable (instance) of a class type
  • state: an instance variable
  • behavior: a method

A simple class

class Point {
  int x;  // an instance variable
  int y;
  // above: members are private by default
 public:
  // below: members are public
  // below are all methods
  Point();  // default constructor
  Point(int x, int y);
  void setX(int x); // mutator/setter
  int getX() {  // accessor/getter, inline definition
    return x;
  }
  void setY(int y); // mutator/setter
  int getY();
};  // end with ;

// out-of-line definition after
Point::Point(): x(0), y(0) {}

Point::Point(int x, int y): x(x), y(y) {}

void Point::setX(int x) {
  this->x = x;
}

void Point::setY(int y) {
  this->y = y;
}

int Point::getY() { return y;}

Class Declaration

  • class keyword (or struct keyword)
  • Usually in header file
  • Semicolon after }
  • Members
    • data member - instance variable
    • function member - method (member function)
  • visibility (access specifier)
    • as sections (different from Java)
      • public: accessible anywhere
      • private: accessible only within objects of the same class
      • protected, etc.: not discussed in the courses
    • default
      • private in class
      • public in struct
    • always prefer information hiding
      • make private if possible
      • almost all instance variables are private
      • only methods to be used out of the class should be public

Methods

  • Inline definitions: in the class declaration

  • Out-of-line definitions: out of the class declaration

    • Scope resolution operator :: to specify the owner of the method (the class)
    • this pointer as a pointer pointing to the current object in method definition
      • use of -> operator
  • Types of methods

    Constructor
    The methods to be triggered when the object is created. Same name as the class. No return type (because they always return the new object). May be overloaded.
    Destructor
    The method to be triggered when the object is destroyed. No parameter. One per class.
    Accessor
    A.k.a getter. A simple method to return the value of an instance variable. Should be const methods in most cases.
    Mutator
    A.k.a setter. Takes one const parameter and set an instance variable to the value passed in.
    Private helper
    A general name of all private methods as they are usually used to help other methods.
  • Constructor

    • No return type
    • Initializer list (read this)
      • constructor only syntax
      • initializes values of instance variables
    • Default constructor
      • no parameter

      • define initial value

      • to trigger

        MyClass obj;
        MyClass obj();
        MyClass obj{};
        MyClass obj[10]; // every element created using the default constructor
        
    • Parameterized constructor
    • Duplication constructors (further discussed here)
      • copy constructor
      • move constructor
  • Const methods: methods that cannot not modify any instance variable

    • any other method called within a const method must be const too
    class MyClass {
      int size;
     public:
      void print() const {
        cout << "Hello!\n";
      }
      int size() const {
        return size;
      }
    };
    

Data Initialization of Non-Static Instance Variable

  1. In-class initializer (constructor only syntax, since c++11)
  2. Initializer list in the constructor (preferred)
  3. Assignment in the constructor
// 1. in-class initializer, always effective
class MyClass {
 private:
  int value = 10;  // <-- here
 public:
  MyClass()=default;  // doing nothing
};

// 2. constructor member initializer list, only affect one constructor
class MyClass {
 private:
  int value;
 public:
  MyClass(): value(10) {}  // <-- here
};

// 3. Naive assignment
class MyClass {
 private:
  int value;
 public:
  MyClass() {
    value = 10;  // <-- here
  }
};

Using Class/Object

  • Declare a variable of a class type

    • Initialization using the constructor:

      MyClass myObj1(10);
      MyClass myObj1 = 10;  // same as the above example
      MyClass myObj1{10}; // since C++11
      
    • Disposable object assignment (Class name followed by parenthesis to trigger the constructor):

      int myFunction(MyClass obj);
      
      int main() {
        // as a parameter, MyClass(10) is a temp object
        cout << myFunction(MyClass(10)) << endl;
      
        // assign to another object
        // copy constructor or copy assignment operator will be triggered
        // MyClass(10) is a temp object
        MyClass objArray[10];  // object array, default constructor triggered
        objArray[0] = MyClass(10);  // copy assignment operator triggered
      }
      
  • . member accessing operator:

    MyClass obj;
    cout << obj.getValue() << endl;
    
  • -> member accessing operator from pointer:

    // pointer to class
    MyClass *objPtr;
    objPtr = new MyClass;
    // objPtr->getValue() is same as (*objPtr).getValue()
    cout << objPtr->getValue() << endl;
    
  • :: Domain resolution operator:

    // Name space
    std::string myString;
    
    // Class method out-of-line definition
    void MyClass::print() {
      cout << "value: " << this->value << endl;
    }
    
    // Class static members
    // static int square(int value) { return value * value};
    MyClass obj1;
    cout << obj1.square(5) << endl;  // use object to access
    cout << MyClass::square(5) << endl;  // use class to access
    

UML Class Diagrams (FYI)

The Unified Modeling Language is a general-purpose modeling language used in software engineering. The class diagram is one type of UML diagram used to model classes and relationships among them in object-oriented programming.

The class diagrams used here is in the PlantUML format. You can check this document for more information.

Example: User Class
class User {
  -string id
  -string name
  +User()
  +User(string id, string name)
  +string getName()
  +string getID()
  }

Static Members (FYI)

  • static keyword
  • one per class
  • global life span
  • stored in the static memory region
  • instance variable
    • data shared among objects

    • can only be initialized outside of the class declaration:

      // my-class.hpp
      class MyClass {
      private:
        static int count;  // NEVER initialize here!
      public:
        // ...
      };
      
      // my-class.cpp
      // omit the static keyword
      int MyClass::count = 10;
      
  • method
    • can not access any instance variable
    • can access static instance variable
    • e.g. pure math functions
    • either MyClass::method() or obj.method() to trigger

Class Example

my-class.hpp

#ifndef MY_CLASS_HPP
#define MY_CLASS_HPP

class MyClass {
 private:  // optional, anything not in the public section is private
  int value;
  void doubleVal();  // private helper
 public:
  MyClass();  // default constructor
  MyClass(int value);  // parameterized constructor
  int getValue() const;  // accessor/getter
  void setValue(int value);  // mutator/setter
  int getDoubledValue();  // general public method
};  // WARNING: must have ; here

#endif // MY_CLASS_HPP

my-class.cpp

#include "my-class.hpp"

void MyClass::doubleVal() {
  value *= 2;
}

int MyClass::getDoubledValue() {
  doubleVal();
  return value;
}

// default constructor
// with initializer list to set value to 0
MyClass::MyClass(): value(0) {}

// parameterized constructor
// using initializer list
// MyClass::MyClass(int value): value(value) {}

// not using initializer list
MyClass::MyClass(int value) {
  // this->value refers to the instance variable
  // must add this-> when names conflict
  this->value = value;
}

int MyClass::getValue() const {
  return value;
}

// cannot use the initializer list because this is not a constructor
void MyClass::setValue(int value) {
  this->value = value;
}

main.cpp

// pay attention to the order
// user header first
// system header last
#include "my-class.hpp"
#include <iostream>

using namespace std;

int main() {
  // trigger the default constructor
  MyClass obj1;
  cout << obj1.getValue() << endl;  // get 0

  // trigger the parameterized constructor
  MyClass obj2(10);
  // alternatives
  // MyClass obj2{10};  // since c++11, preferred
  // MyClass obj2 = 10;  // trigger the parameterized constructor
  cout << obj2.getValue() << endl;  // get 10

  MyClass *ptr1;
  ptr1 = new MyClass(15);  // use new to call the constructor
  cout << ptr1->getValue() << endl;  // get 15
  cout << (*ptr1).getValue() << endl;  // get 15
}

makefile

main: main.o my-class.o
    g++ -o $@ $^

main.o: main.cpp my-class.hpp
    g++ -std=c++14 -Wall -c -o $@ $<

my-class.o: my-class.cpp my-class.hpp
    g++ -std=c++14 -Wall -c -o $@ $<

clean:
    rm -f *.o main