Programming in C++

Introduction to Object Oriented Programming (OOP)

Structs (Composite Data Types)

Gerald Senarclens de Grancy

What are C++ Structs

C++ structs are, in terms of functionality, a superset of C structs

C++ structs allow to store multiple variables (data members) along with behavior (member functions)

C++ structs allow encapsulation and inheritance

The only difference between struct and class in C++ are

  • access specifier defaults to public for struct and private for class
  • inheritance defaults to public for struct and private for class

Advantages of C++ Structs

C++ structs allow real OOP including advanced concepts such as encapsulation and inheritance

Disadvantages of C++ Structs

In C++ struct and class are (besides their default access specifier) identical which can lead to confusion

It is recommended to use struct in C++ similar to the much more limited struct in C

C++ Core Guidelines

  • Use struct if the data members can vary independently

Google C++ Style Guide

  • Use a struct only for passive objects that carry data
  • The struct must not have invariants that imply relationships between different fields

Defining a C++ struct

struct StructName {
StructName(); // constructors are supported
~StructName(); // destructors are supported

type member1;
type member2;
/* declare as many members as desired */

type method1(param1, ...);
type method2(.);
/* declare as many methods as desired */
};

Example: struct Point

#include <iostream>
struct Point {
int x = 0; // default values are allowed since C++11
int y = 0;
};
int main() {
Point p; // Create Point object (instance); initialize with default values
std::cout << "x: " << p.x << ", y: " << p.y << std::endl;
Point p2{ .x = 5, .y = 3 }; // Create another instance with given values
p2.x = 4; // members are public by default
std::cout << "x: " << p2.x << ", y: " << p2.y << std::endl;
return 0;
}

Visualize execution

A C++ struct can have methods

Data fields are directly available

Example: Member Functions

#include <iostream>
struct Point {
int x = 0; // default values are allowed since C++11
int y = 0;
void print() {
std::cout << "x: " << x << ", y: " << y << std::endl;
}
};
int main() {
Point p{ .x = 5, .y = 3 }; // initialize with given values
p.print();
return 0;
}

Visualize execution

Member access can be explicit using the this pointer

Example: this

#include <iostream>
struct Point {
int x = 0;
int y = 0;
void print() {
std::cout << "x: " << (*this).x << ", y: " << this->y << std::endl;
}
};
int main() {
Point p{ .x = 5, .y = 3 }; // initialize with given values
p.print();
return 0;
}

Visualize execution

Constructor and Destructor

In OOP, a constructor (abbreviation: ctor) is a special type of method called to create an object

A destructor (sometimes abbreviated dtor) is a method which is invoked just before the memory of the object is released

Example: Constructor for Point

#include <iostream>
struct Point {
int x = 0; // default values are allowed since C++11
int y = 0;
Point(int x, int y) : x(x), y(y) {} // constructor with initializer list
Point() : Point(0, 0) {} // Point() delegates to Point(0, 0)
void print() {
std::cout << "x: " << x << ", y: " << y << std::endl;
}
};
int main() {
Point p1 = Point(); // use constructor without arguments
Point p2 = Point(5, 3); // use constructor with arguments
p2.print();
return 0;
}

Visualize execution

Free Store

In C++, the free store can be used with the new and delete keywords.

#include <iostream>

struct Point {
int x;
int y;
Point(int x, int y) : x(x), y(y) {} // constructor with initializer list
Point() : Point(0, 0) {} // Point() delegates to Point(0, 0)
void print() {
std::cout << "x: " << x << ", y: " << y << std::endl;
}
};
int main() {
Point* p = new Point(5, 3); // create object on the free store
p->print();
delete p; // free the reserved memory
return 0;
}

Visualize execution

Separate Declaration and Definition

To use a struct in other files, declare it in a header file

Structs are usually also defined in header files

Struct methods are declared in the struct definition but defined in a designated source file

C++ Core Guidelines

  • Explicit distinction between interface (*.hpp) and implementation (*.cpp) improves readability and simplifies maintenance

Example: Header File Contains the API

#ifndef POINT_HPP
#define POINT_HPP

namespace draw {
struct Point {
int x;
int y;
Point(int x, int y); // constructor is declared, not defined
Point();
void print(); // method is declared, not defined
};
}

#endif
Download point.hpp

Example: Source File

#include "point.hpp"
#include <iostream>

namespace draw {
Point::Point(int x, int y) : x(x), y(y) {}; // constructor within class scope
Point::Point() : Point(0, 0) {}; // Point() delegates to Point(0, 0)
void Point::print() { // method within class scope
std::cout << "x: " << x << ", y: " << y << std::endl;
};
}
Download point.cpp

Example: Use the struct

The struct can be used from any other file

#include "point.hpp"

int main(void) {
draw::Point p1(3, 4); // create instance of Point from namespace draw
draw::Point p2(5, 0); // create another object (instance)
p1.print();
p2.print();
}
Download main.cpp

Compile the program with clang++ main.cpp point.cpp

Key Differences from C

In C++, struct is much more powerful than in C

  • C++ struct can have member functions (methods)
  • C++ struct can have constructors and destructors
  • this keyword is a reference to the current instance
    this is implicitly passed to every method
  • struct keyword not needed when creating an instance
    ⇒ no need to typedef a simple struct
  • C++11 allows default values for struct properties

C++ structs are even more powerful, but it is best practice to resort to use classes instead when those features are needed

Questions
and feedback...