Objects and Classes in C++

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
 1class Point {
 2  int x;  // an instance variable
 3  int y;
 4  // above: members are private by default
 5 public:
 6  // below: members are public
 7  // below are all methods
 8  Point();  // default constructor
 9  Point(int x, int y);
10  void setX(int x); // mutator/setter
11  int getX() {  // accessor/getter, inline definition
12    return x;
13  }
14  void setY(int y); // mutator/setter
15  int getY();
16};  // end with ;
17
18// out-of-line definition after
19Point::Point(): x(0), y(0) {}
20
21Point::Point(int x, int y): x(x), y(y) {}
22
23void Point::setX(int x) {
24  this->x = x;
25}
26
27void Point::setY(int y) {
28  this->y = y;
29}
30
31int 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

     1class MyClass {
     2  int size;
     3 public:
     4  void print() const {
     5    cout << "Hello!\n";
     6  }
     7  int size() const {
     8    return size;
     9  }
    10};
    

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

Note

Two methods can be mixed. Use the first method for initial values shared among multiple constructors; Use the second method for values that differs among various constructors. When used together, the first will be ignored.

 1// 1. in-class initializer, always effective
 2class MyClass {
 3 private:
 4  int value = 10;  // <-- here
 5 public:
 6  MyClass()=default;  // doing nothing
 7};
 8
 9// 2. constructor member initializer list, only affect one constructor
10class MyClass {
11 private:
12  int value;
13 public:
14  MyClass(): value(10) {}  // <-- here
15};
16
17// 3. Naive assignment
18class MyClass {
19 private:
20  int value;
21 public:
22  MyClass() {
23    value = 10;  // <-- here
24  }
25};

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

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

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

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

     1// Name space
     2std::string myString;
     3
     4// Class method out-of-line definition
     5void MyClass::print() {
     6  cout << "value: " << this->value << endl;
     7}
     8
     9// Class static members
    10// static int square(int value) { return value * value};
    11MyClass obj1;
    12cout << obj1.square(5) << endl;  // use object to access
    13cout << 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
1class User {
2  -string id
3  -string name
4  +User()
5  +User(string id, string name)
6  +string getName()
7  +string getID()
8  }

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:

       1// my-class.hpp
       2class MyClass {
       3private:
       4  static int count;  // NEVER initialize here!
       5public:
       6  // ...
       7};
       8
       9// my-class.cpp
      10// omit the static keyword
      11int 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
 1#ifndef MY_CLASS_HPP
 2#define MY_CLASS_HPP
 3
 4class MyClass {
 5 private:  // optional, anything not in the public section is private
 6  int value;
 7  void doubleVal();  // private helper
 8 public:
 9  MyClass();  // default constructor
10  MyClass(int value);  // parameterized constructor
11  int getValue() const;  // accessor/getter
12  void setValue(int value);  // mutator/setter
13  int getDoubledValue();  // general public method
14};  // WARNING: must have ; here
15
16#endif // MY_CLASS_HPP
my-class.cpp
 1#include "my-class.hpp"
 2
 3void MyClass::doubleVal() {
 4  value *= 2;
 5}
 6
 7int MyClass::getDoubledValue() {
 8  doubleVal();
 9  return value;
10}
11
12// default constructor
13// with initializer list to set value to 0
14MyClass::MyClass(): value(0) {}
15
16// parameterized constructor
17// using initializer list
18// MyClass::MyClass(int value): value(value) {}
19
20// not using initializer list
21MyClass::MyClass(int value) {
22  // this->value refers to the instance variable
23  // must add this-> when names conflict
24  this->value = value;
25}
26
27int MyClass::getValue() const {
28  return value;
29}
30
31// cannot use the initializer list because this is not a constructor
32void MyClass::setValue(int value) {
33  this->value = value;
34}
main.cpp
 1// pay attention to the order
 2// user header first
 3// system header last
 4#include "my-class.hpp"
 5#include <iostream>
 6
 7using namespace std;
 8
 9int main() {
10  // trigger the default constructor
11  MyClass obj1;
12  cout << obj1.getValue() << endl;  // get 0
13
14  // trigger the parameterized constructor
15  MyClass obj2(10);
16  // alternatives
17  // MyClass obj2{10};  // since c++11, preferred
18  // MyClass obj2 = 10;  // trigger the parameterized constructor
19  cout << obj2.getValue() << endl;  // get 10
20
21  MyClass *ptr1;
22  ptr1 = new MyClass(15);  // use new to call the constructor
23  cout << ptr1->getValue() << endl;  // get 15
24  cout << (*ptr1).getValue() << endl;  // get 15
25}
makefile
 1main: main.o my-class.o
 2    g++ -o $@ $^
 3
 4main.o: main.cpp my-class.hpp
 5    g++ -std=c++14 -Wall -c -o $@ $<
 6
 7my-class.o: my-class.cpp my-class.hpp
 8    g++ -std=c++14 -Wall -c -o $@ $<
 9
10clean:
11    rm -f *.o main