0% found this document useful (0 votes)
4 views41 pages

CPP Classes Deep Dive

This study guide provides a comprehensive overview of C++ classes, covering essential concepts such as class anatomy, data members, member functions, access specifiers, and inheritance. It uses the OpenLB cylinder2d.cpp example to illustrate how classes bundle data and behavior together, enhancing code organization and safety. Each chapter builds progressively on the previous one, culminating in an explanation of all classes in the cylinder2d.cpp file.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views41 pages

CPP Classes Deep Dive

This study guide provides a comprehensive overview of C++ classes, covering essential concepts such as class anatomy, data members, member functions, access specifiers, and inheritance. It uses the OpenLB cylinder2d.cpp example to illustrate how classes bundle data and behavior together, enhancing code organization and safety. Each chapter builds progressively on the previous one, culminating in an explanation of all classes in the cylinder2d.cpp file.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

C++ Classes — Deep Dive Study Guide | cylinder2d.

cpp Page 1

C++ Classes
A Complete, Example-Driven Deep Dive

From first principles — objects, methods, constructors, access, inheritance, polymorphism


— to every class in [Link]

Logical · Engineering · Tree-Structure format

Based on the OpenLB [Link] example

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 2

Chapter 0

Learning Map — Your Path Through This


Guide
This guide is structured as a progressive journey. Each chapter adds one layer to your understanding of C++
classes. Read front-to-back the first time, then use the chapter list as a reference.

Chap Topic What you will be able to do after reading


ter

0 Learning map Navigate this guide

1 The problem classes solve Explain WHY classes exist

2 Class anatomy Name every part of a class declaration

3 Data members (fields) Declare and use instance variables

4 Member functions Write and call methods; understand const methods


(methods)

5 Access specifiers Use public, private, protected correctly

6 Constructors Read and write all forms of constructors

7 Destructors Understand automatic cleanup

8 The dot and arrow operators Access members of objects and pointers

9 Static members Understand class-wide shared data/functions

10 Inheritance Read base/derived class relationships

11 Virtual functions Understand polymorphism and override

12 const correctness Apply const to members and functions

13 Object lifetime & memory Know when objects are created/destroyed

14 Every class in cylinder2d Explain every OpenLB class in the file

15 Common mistakes Avoid the 10 most frequent class errors

■ Tip
Chapters 1–8 are the essential foundation. Read them carefully and try each code example
mentally. Chapters 9–13 add important details. Chapter 14 is the payoff — where everything
connects to [Link].

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 3

Chapter 1

The Problem Classes Solve — WHY Do They


Exist?
1.1 The world before classes — functions and loose data
Imagine you need to write a program to manage bank accounts. Without classes, you use separate variables
and separate functions:

// WITHOUT classes — data and functions are disconnected


double balance1 = 1000.0;
double balance2 = 500.0;
std::string owner1 = "Alice";
std::string owner2 = "Bob";

// Functions must receive data as parameters — fragile!


void deposit(double& balance, double amount) {
balance += amount;
}
bool withdraw(double& balance, double amount) {
if (amount > balance) return false;
balance -= amount;
return true;
}

// Usage — easy to accidentally mix up variables:


deposit(balance1, 200); // OK: Alice deposits
deposit(balance2, balance1); // BUG: passed wrong thing — no compiler help!

Without classes: data and logic are disconnected — error-prone

Problems with this approach:

• Data and the functions that operate on it are physically separated — nothing enforces they belong
together
• You can accidentally pass the wrong variable — the compiler cannot catch it
• With 100 accounts, you have 200 loose variables and no structure
• Adding a new field (e.g. account number) requires changing every function

1.2 Classes solve this — bundle data AND behaviour together


// WITH classes — data and behaviour are one unit
class BankAccount {
private:

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 4

double balance; // data hidden inside the class


std::string owner;

public:
// Constructor: sets up the account when created
BankAccount(std::string name, double initial)
: owner(name), balance(initial) {}

void deposit(double amount) { balance += amount; }


bool withdraw(double amount) {
if (amount > balance) return false;
balance -= amount;
return true;
}
double getBalance() const { return balance; }
std::string getOwner() const { return owner; }
};

// Usage — clean, safe, impossible to confuse accounts:


BankAccount alice("Alice", 1000.0);
BankAccount bob("Bob", 500.0);

[Link](200.0); // clearly Alice's account


[Link](100.0); // clearly Bob's account
[Link]([Link]()); // readable and intentional

With classes: data and logic are one unit — safe and readable

■ Analogy
A class is like a blueprint for a machine. The blueprint defines what the machine contains (its parts
= data members) and what it can do (its buttons = methods). An object is a specific machine built
from that blueprint. You can build many machines from one blueprint — each has its own parts but
shares the same instruction manual (methods).

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 5

Chapter 2

Class Anatomy — Every Part of a Class


Declaration
2.1 The visual map

← Class name declaration


class BankAccount {

private:
double balance;
std::string owner;
← Data members (fields)
void validate(double amt);
public: ← Private method
BankAccount(string name, double b);
void deposit(double amount);
← Constructor
bool withdraw(double amount);
double getBalance() const;
← Member functions (methods)
~BankAccount();

}; ← Closing brace + semicolon


Destructor

Figure 1 — Anatomy of a C++ class

2.2 The six parts of a class


Part Keyword / symbol Required? What it does

Class keyword class or struct YES Declares that what follows is a class
definition

Class name identifier YES The name you use to create objects of
this type

Opening brace { YES Starts the class body

Access specifier public / private / Recommende Controls who can see the members
protected d below it

Members variables & functions Usually The data and behaviour of the class

Closing brace + ; }; YES Ends the class definition. The


semicolon is REQUIRED

// Minimal legal class — technically valid but useless:


class Empty {};

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 6

// class vs struct: the ONLY difference is default access


class MyClass { /* default: private */ };
struct MyStruct { /* default: public */ };

// In OpenLB, 'struct' is often used for simple data-holder types


// and 'class' for full-featured simulation objects.

■ Watch out
The semicolon after the closing brace }; is unique to classes (and structs, enums). Functions do
NOT need a semicolon after }. Forgetting it causes confusing compile errors on the NEXT line.

2.3 class vs struct — the only real difference


class Dog { struct Dog {
// default: private // default: public
std::string name; std::string name; // accessible directly!
int age; int age;
}; };

Dog d1;
[Link] = "Rex"; // ERROR: name is private in class

Dog d2;
[Link] = "Rex"; // OK: name is public in struct

// In practice: use struct for simple data bags, class for full objects.
// OpenLB uses struct for descriptors (D2Q9) and class for simulation
objects.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 7

Chapter 3

Data Members — The State of an Object


3.1 What are data members?
Data members (also called fields, instance variables, or attributes) are variables declared inside a class.
Each object gets its own separate copy of every data member:

class Particle {
public:
double x, y; // position
double vx, vy; // velocity
double mass; // mass
int id; // unique identifier
};

// Each object has its OWN copy of all fields:


Particle p1; p1.x = 1.0; p1.y = 2.0; [Link] = 1.5;
Particle p2; p2.x = 5.0; p2.y = 3.0; [Link] = 2.0;

// p1 and p2 are completely independent — changing p1.x does NOT affect p2.x
p1.x = 99.0;
// p2.x is still 5.0

Two BankAccount objects in memory:

obj1 obj2
balance 8 bytes balance 8 bytes

owner ptr 8 bytes owner ptr 8 bytes

Figure 4 — Data is per-object (separate copies); methods are shared (one copy in memory)
Methods (shared code)
deposit, withdraw, getBalance...

3.2 Static data members — shared by ALL objects


A static data member is shared across all instances of the class — there is only one copy no matter how
many objects you create:

class Particle {
public:
double x, y; // per-object: each particle has its own
static int particleCount; // shared: one value for ALL particles

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 8

Particle() { particleCount++; } // increment when created


~Particle(){ particleCount--; } // decrement when destroyed
};

// MUST define the static member outside the class:


int Particle::particleCount = 0;

Particle p1, p2, p3;


Particle::particleCount; // = 3 (shared by all)
[Link]; // also 3 — same value accessed via object

■ Tip
In OpenLB, static members are used in descriptor classes (like D2Q9) to store compile-time
constants: number of velocities, weight factors, lattice vectors — values that are the same for all
lattice cells and never change.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 9

Chapter 4

Member Functions — The Behaviour of an


Object
4.1 What is a member function?
A member function (also called a method) is a function declared inside a class. It can access ALL of the
class's data members directly, without them being passed as parameters. This is the key power of classes —
the function 'knows' its data:

class Thermometer {
private:
double tempCelsius;

public:
Thermometer(double t) : tempCelsius(t) {}

// Method: accesses tempCelsius directly — no parameter needed


double getCelsius() const { return tempCelsius; }
double getFahrenheit() const { return tempCelsius * 9.0/5.0 + 32.0; }
double getKelvin() const { return tempCelsius + 273.15; }

void setTemp(double t) { tempCelsius = t; }


void heatBy(double dt) { tempCelsius += dt; }
};

Thermometer t(25.0); // 25°C


[Link](); // returns 77.0°F
[Link](10.0); // now 35°C
[Link](); // returns 308.15 K

4.2 const member functions — the 'I promise not to modify' declaration
A method marked const after its parameter list promises: "calling this function will NOT change any data
member." This is critically important in OpenLB where you pass objects as const& references:

class Circle {
double radius;
public:
Circle(double r) : radius(r) {}

double getRadius() const { return radius; } // const: safe read-only


double area() const { return 3.14159 * radius * radius; }
double perimeter() const { return 2 * 3.14159 * radius; }

void scale(double factor) { radius *= factor; } // non-const: modifies

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 10

};

// A const object can ONLY call const methods:


const Circle c(5.0);
[Link](); // OK: area() is const
[Link](2.0); // COMPILE ERROR: scale() is non-const on a const object

// A const reference can ONLY call const methods:


void printInfo(const Circle& c) {
[Link](); // OK
[Link](2.0); // COMPILE ERROR
}

■ In OpenLB
In [Link], the UnitConverter is passed as const UnitConverter<T,DESCRIPTOR>&
converter. This means only const methods of converter can be called inside that function.
getLatticeTime(), getCharLatticeVelocity(), getLatticeRelaxationFrequency() etc. are all const
methods — they only read, never modify.

4.3 The 'this' pointer — the hidden parameter


Every non-static member function receives a hidden pointer called this that points to the object it was called
on. You rarely need to use it explicitly, but understanding it helps:

class Counter {
int count;
public:
Counter(int c) : count(c) {}

void increment() {
count++; // same as: this->count++
// 'this' is a hidden pointer to the current object
}

// Explicit 'this' use — chaining:


Counter& add(int n) {
this->count += n;
return *this; // return the object itself for chaining
}
};

Counter c(0);
[Link](5).add(3).add(2); // chaining: [Link] = 10

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 11

■ Tip
You see method chaining in OpenLB with the output stream: clout << "x=" << x << std::endl; Each
<< returns the stream itself (*this), enabling the next <<.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 12

Chapter 5

Access Specifiers — public, private,


protected
5.1 The three access levels — a visual map

public

— visible EVERYWHERE: inside the class, from objects, from derived classes, from anywhere

protected

— visible INSIDE the class and in DERIVED classes only

private

— visible ONLY inside THIS class (default for 'class' keyword)

Figure 3 — Access specifier zones (nested: outer = widest access)

5.2 private — the default for class, the most restrictive


Private members are accessible only from within the class itself. Not from derived classes. Not from user
code. Only from the class's own methods:

class Password {
private:
std::string secret; // only Password's own methods can touch this

public:
Password(std::string s) : secret(s) {}
bool check(std::string attempt) { return attempt == secret; }
// Notice: no 'getSecret()' method — intentional!
};

Password p("hunter2");
[Link]; // COMPILE ERROR: secret is private
[Link]("hunter2"); // OK: check() is public and internally accesses secret

■ Key concept
Encapsulation: hiding private data and exposing only a controlled public interface is one of the most
important principles of object-oriented design. It lets you change the internal implementation without
breaking user code.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 13

5.3 public — accessible from everywhere


class Sensor {
public: // everything below is public
double read() { return rawValue * calibration; }
void calibrate(double c) { calibration = c; }

private:
double rawValue = 0.0; // hidden
double calibration = 1.0; // hidden
};

Sensor s;
[Link](1.05); // OK: public method
[Link](); // OK: public method
[Link]; // ERROR: private

5.4 protected — for inheritance


Protected members are private to outside code, but accessible to derived classes (children in inheritance).
You will see this in OpenLB's base classes:

class Animal {
protected:
double energy; // derived classes can access this
std::string name;

public:
Animal(std::string n, double e) : name(n), energy(e) {}
std::string getName() const { return name; }
};

class Dog : public Animal {


public:
Dog(std::string n) : Animal(n, 100.0) {}

void eat(double food) {


energy += food; // OK: energy is protected — Dog CAN access it
}
void bark() {
energy -= 5.0; // OK: same
}
};

Dog rex("Rex");
[Link] = 200; // COMPILE ERROR: protected — outside code cannot touch it

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 14

[Link](10); // OK: public method

■ In OpenLB
In OpenLB's IndicatorF2D base class, the bounding-box arrays _myMin and _myMax are protected
— derived classes like IndicatorCircle2D can read and set them, but user code (your
[Link]) cannot access them directly.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 15

Chapter 6

Constructors — Building an Object


6.1 What is a constructor?
A constructor is a special member function that is called automatically when an object is created. Its job is
to put the object into a valid initial state. Two rules make it special: it has the same name as the class and it
has no return type (not even void):

class Robot {
private:
std::string name;
int batteryLevel;
bool isOn;

public:
// Constructor — same name as class, no return type
Robot(std::string robotName, int battery) {
name = robotName;
batteryLevel = battery;
isOn = false; // always starts off
}
void turnOn() { isOn = true; }
bool alive() const { return batteryLevel > 0; }
};

// Constructor called automatically when object is created:


Robot r1("R2D2", 100); // [Link]="R2D2", [Link]=100, [Link]=false
Robot r2("C3PO", 80); // r2 is independent — its own copy of all fields

6.2 The member initialiser list — the preferred syntax


The preferred way to initialise members in a constructor is using the member initialiser list — the colon
syntax between the parameter list and the body. This initialises members directly instead of assigning to
them after construction (more efficient and required for const members and references):

class Robot {
std::string name;
int batteryLevel;
const int serialNumber; // const member — MUST use initialiser list

public:
// Initialiser list style (preferred):
// : member1(arg1), member2(arg2), ...

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 16

Robot(std::string n, int bat, int serial)


: name(n), batteryLevel(bat), serialNumber(serial) {
// body: for additional logic only
}

// Assignment style (works but less efficient for objects):


Robot(std::string n, int bat) {
name = n; // first default-constructs name, then assigns
batteryLevel = bat; // inefficient for std::string
// serialNumber = 5; // COMPILE ERROR: can't assign to const after
construction
}
};

■ In OpenLB
Every OpenLB constructor uses the initialiser list style. Example from UnitConverter: the six
physical parameters (physDeltaX, physDeltaT, charPhysLength, etc.) are all stored as const
members and must be initialised via the list, not assigned in the body.

6.3 Types of constructors


Type Syntax Called when Example

Default constructor ClassName() Object created with no Robot r;


arguments

Parameterised ctor ClassName(args) Object created with Robot r("R2D2", 100)


arguments

Copy constructor ClassName(const C& Object copied from another Robot r2 = r1;
other)

Move constructor ClassName(C&& other) Object moved (transfer Robot r2 =


ownership) std::move(r1)

Delegating ctor ClassName() : One ctor calls another ctor Robot() :


ClassName(args) Robot("default",50){}

class Point {
double x, y;
public:
Point() : x(0), y(0) {} // default constructor
Point(double a, double b) : x(a), y(b) {} // parameterised
Point(const Point& p): x(p.x),y(p.y) {} // copy constructor
};

Point p1; // default ctor: p1 = (0, 0)


Point p2(3.0, 4.0); // parameterised: p2 = (3, 4)

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 17

Point p3 = p2; // copy ctor: p3 = (3, 4), independent copy


Point p4(p2); // same as above — explicit copy constructor call

6.4 Constructor delegation — one constructor calling another


class Simulation {
int nx, ny;
double physLength;
double viscosity;

public:
// Full constructor:
Simulation(int x, int y, double L, double nu)
: nx(x), ny(y), physLength(L), viscosity(nu) {}

// Delegating constructor — calls the full one with defaults:


Simulation() : Simulation(100, 50, 2.2, 0.001) {}

// Another delegating constructor:


Simulation(int resolution) : Simulation(resolution, resolution/2, 2.2,
0.001) {}
};

Simulation s1; // default: 100x50, L=2.2, nu=0.001


Simulation s2(200); // 200x100
Simulation s3(220, 110, 4.4, 0.002); // full specification

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 18

Chapter 7

Destructors — Automatic Cleanup


7.1 What is a destructor?
A destructor is called automatically when an object's lifetime ends — when it goes out of scope or is deleted.
It has the same name as the class but prefixed with a tilde ~ and takes no parameters:

class FileWriter {
FILE* file;
public:
FileWriter(const char* path) {
file = fopen(path, "w");
std::cout << "File opened" << std::endl;
}

void write(const char* text) { fputs(text, file); }

~FileWriter() { // destructor: ~ prefix, no parameters


fclose(file); // automatically close file
std::cout << "File closed" << std::endl;
}
};

void doWork() {
FileWriter fw("[Link]"); // constructor called: file opened
[Link]("hello\n");
[Link]("world\n");
// Function ends -> fw goes out of scope -> destructor called: file
closed
} // <- destructor runs HERE automatically

■ Key concept
This automatic cleanup pattern is called RAII: Resource Acquisition Is Initialisation. The resource
(file, memory, GPU buffer) is acquired in the constructor and released in the destructor. You never
need to manually call cleanup code. OpenLB uses this extensively — SuperLattice allocates GPU
memory in its constructor and frees it in its destructor, automatically, when main() exits.

7.2 Destructor call order


int main() {
// Objects created in this order:
UnitConverter<T,D> converter(...); // 1st created
SuperGeometry<T,2> superGeometry(...); // 2nd created

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 19

SuperLattice<T,D> sLattice(...); // 3rd created

// ... simulation runs ...

return 0;
// Destructors called in REVERSE order:
// 1st destroyed: sLattice (frees GPU memory / lattice data)
// 2nd destroyed: superGeometry (frees geometry data)
// 3rd destroyed: converter (nothing to free — only numbers)
}

■ Tip
C++ always destroys local objects in reverse order of creation (Last In First Out). This is important
because sLattice may hold references to superGeometry — destroying sLattice first ensures it can
clean up safely before superGeometry disappears.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 20

Chapter 8

The Dot (.) and Arrow (->) Operators


8.1 Visual comparison

Dot operator . (object) Arrow operator -> (pointer)

SuperGeometry<T,2> sg; SuperGeometry<T,2>* ptr;


[Link](0, 2); ptr->rename(0, 2);

[Link](); ptr->clean();

[Link](); // same as (*ptr).clean()


sg is an OBJECT (not a pointer) ptr is a POINTER to an object

Figure 6 — Dot (.) vs Arrow (->) operator: object vs pointer access

8.2 Dot operator — for objects


// Dot operator: [Link] or [Link](args)

SuperGeometry<T,2> superGeometry(...); // superGeometry IS an object

[Link](0, 2); // call method rename()


[Link](); // call method clean()
[Link](); // call method checkForErrors()
[Link](); // call method print()

// More examples with other types:


std::string name = "Alice";
[Link](); // call length() method on the string object
[Link](0, 3); // call substr() method

UnitConverter<T,D> converter(...);
[Link](maxPhysT); // call method on converter
[Link]();
[Link]();

8.3 Arrow operator — for pointers to objects


// Arrow operator: ptr->member or ptr->method(args)
// ptr->method() is exactly the same as (*ptr).method()

SuperGeometry<T,2>* ptr = &superGeometry; // ptr is a POINTER

ptr->rename(0, 2); // same as (*ptr).rename(0, 2)


ptr->clean(); // same as (*ptr).clean()

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 21

// When do you see -> in OpenLB?


// Internally the library uses pointers and smart pointers.
// As a user, you mostly use objects directly (dot operator).

// However, singleton::mpi() returns a reference/object-like thing:


singleton::mpi().getSize(); // dot operator on the returned object

■ Tip
Rule: if the variable is declared as 'TypeName obj' use dot (.). If it is declared as 'TypeName* ptr'
use arrow (->). If you ever see 'invalid use of incomplete type' or 'request for member X in Y which
is of pointer type' — you are probably using the wrong operator.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 22

Chapter 9

Static Members — Class-Wide Shared Data


and Functions
9.1 Static member functions — callable without an object
A static member function belongs to the class itself, not to any specific object. You call it with the class
name and ::, not via an object:

class MathUtils {
public:
// Static methods: no 'this' pointer, no object needed
static double clamp(double v, double lo, double hi) {
return (v < lo) ? lo : (v > hi) ? hi : v;
}
static double lerp(double a, double b, double t) {
return a + t * (b - a);
}
static constexpr double PI = 3.14159265358979;
};

// Call via class name — no object needed:


double clamped = MathUtils::clamp(7.5, 0.0, 5.0); // 5.0
double interp = MathUtils::lerp(0.0, 10.0, 0.3); // 3.0
double pi = MathUtils::PI;

// Can also call via an object (but unusual style):


MathUtils m;
[Link](7.5, 0.0, 5.0); // works but misleading

■ In OpenLB
singleton::mpi() in [Link] is a static-like pattern — it returns the one shared MPI
environment object. descriptor structs like D2Q9 have static constexpr members: the number of
velocities (q=9), lattice velocities c[], weights w[] — all shared across all uses of D2Q9.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 23

Chapter 10

Inheritance — Building Hierarchies with 'is-a'


10.1 The concept
Inheritance lets a new class (derived class / child) automatically gain all members of an existing class (base
class / parent), then add its own members or override existing behaviour. The relationship is 'is-a':

// Base class: the general concept


class Shape {
protected:
std::string colour;
public:
Shape(std::string c) : colour(c) {}
std::string getColour() const { return colour; }
virtual double area() const = 0; // pure virtual: MUST override
virtual double perimeter() const = 0; // pure virtual
virtual ~Shape() {} // virtual destructor (important!)
};

// Derived class: inherits from Shape using ': public Shape'


class Circle : public Shape {
double radius;
public:
Circle(double r, std::string c) : Shape(c), radius(r) {}
double area() const override { return 3.14159 * radius * radius; }
double perimeter() const override { return 2 * 3.14159 * radius; }
double getRadius() const { return radius; }
};

class Rectangle : public Shape {


double w, h;
public:
Rectangle(double w, double h, std::string c) : Shape(c), w(w), h(h) {}
double area() const override { return w * h; }
double perimeter() const override { return 2*(w+h); }
};

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 24

IndicatorF2D&lt;T&gt; (Base)

+ operator()(x,y) = 0

# _myMin[2]

# _myMax[2]

inherits from (is-a relationship)


IndicatorCuboid2D IndicatorCircle2DIndicatorCylinder3D

+ operator()(x,y) + operator()(x,y) + operator()(x,y,z)

- _extend[2] - _centre[2] - _centre[3]

- _origin[2] - _radius - _radius

Rect region Circle region 3D cylinder

Figure 5 — IndicatorF2D&lt;T&gt; inheritance hierarchy in OpenLB

10.2 Inheritance syntax breakdown


// Syntax: class DerivedName : AccessSpecifier BaseClassName { ... };
// ^^^^^^^^^^^^^^
// almost always 'public' for inheritance

class Circle : public Shape { ... };


// Circle IS-A Shape: a Circle object IS a Shape object
// Circle HAS everything Shape has, PLUS its own radius

// In OpenLB:
class IndicatorCircle2D : public IndicatorF2D<T> { ... };
// IndicatorCircle2D IS-A IndicatorF2D
// It has everything IndicatorF2D has, plus centre and radius

10.3 What is inherited and what is not


From base class Inherited by Notes
derived?

public members YES Accessible from derived and outside

protected members YES Accessible from derived only

private members NO (but they exist!) Data exists in memory but cannot be accessed
directly — use protected or accessor methods

Constructors NO Each class defines its own constructors

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 25

Destructor NO (but called!) Base destructor is called automatically after


derived destructor

Assignment operator NO (default Compiler creates one if not defined


synthesised)

class Dog : public Animal {


public:
Dog(std::string name) : Animal(name, 100.0) {
// Dog's constructor MUST call Animal's constructor
// to initialise the inherited parts
}
~Dog() {
// Dog's destructor runs first, then Animal's destructor
// automatically — no need to call it manually
}
};

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 26

Chapter 11

Virtual Functions and Polymorphism


11.1 The problem — without virtual
class Animal {
public:
void speak() { std::cout << "..." << std::endl; } // NOT virtual
};

class Dog : public Animal {


public:
void speak() { std::cout << "Woof!" << std::endl; }
};

// Without virtual — which speak() is called depends on the POINTER type:


Dog d;
[Link](); // 'Woof!' — obvious

Animal* ptr = &d; // Animal pointer pointing to a Dog


ptr->speak(); // '...' — WRONG! Called Animal's version
// because ptr is Animal* at compile time

Without virtual: the pointer type determines which method runs — bad!

11.2 virtual — runtime dispatch


class Animal {
public:
virtual void speak() { std::cout << "..." << std::endl; }
virtual ~Animal() {} // ALWAYS make destructor virtual in base classes
};

class Dog : public Animal {


public:
void speak() override { std::cout << "Woof!" << std::endl; }
};

class Cat : public Animal {


public:
void speak() override { std::cout << "Meow!" << std::endl; }
};

// With virtual — the OBJECT type determines which method runs:


Animal* animals[3];
animals[0] = new Dog();

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 27

animals[1] = new Cat();


animals[2] = new Dog();

for (int i = 0; i < 3; i++) {


animals[i]->speak(); // 'Woof!', 'Meow!', 'Woof!'
} // correct! runtime dispatch based on actual type

With virtual: the actual object type determines which method runs — correct!

11.3 Pure virtual functions — abstract classes


// = 0 makes a function PURE VIRTUAL
// A class with any pure virtual function is ABSTRACT:
// - You cannot create objects of it directly
// - Derived classes MUST override it

class IndicatorF2D {
public:
// Pure virtual: every derived class MUST implement this
virtual bool operator()(bool output[], const double input[]) = 0;
virtual ~IndicatorF2D() {}
};

// IndicatorF2D obj; // COMPILE ERROR: cannot instantiate abstract class

// IndicatorCircle2D provides the implementation:


class IndicatorCircle2D : public IndicatorF2D<T> {
public:
bool operator()(bool output[], const double input[]) override {
double dx = input[0] - cx;
double dy = input[1] - cy;
output[0] = (dx*dx + dy*dy <= radius*radius);
return output[0];
}
};

IndicatorCircle2D c(center, radius); // OK: concrete class


// Pass as base class reference — polymorphism at work:
void useIndicator(IndicatorF2D<T>& ind) { /* calls correct operator() */ }
useIndicator(c); // works!

■ In OpenLB
Every IndicatorF2D-derived class in OpenLB overrides operator() to answer 'is point (x,y) inside this
region?'. This is exactly how prepareGeometry uses the circle indicator — it receives
IndicatorF2D<T>& and calls it as a function to test whether each cell is inside the cylinder.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 28

Chapter 12

const Correctness — The Discipline of Not


Modifying What You Should Not
12.1 The four positions of const in class code
// POSITION 1: const data member — never changes after construction
class Converter {
const double physDeltaX; // set in constructor, never changes
const double physDeltaT;
public:
Converter(double dx, double dt) : physDeltaX(dx), physDeltaT(dt) {}
};

// POSITION 2: const method — does not modify the object


class Circle {
double r;
public:
double area() const { return 3.14159 * r * r; } // const method
void resize(double f) { r *= f; } // non-const method
};

// POSITION 3: const parameter — does not modify the argument


void printCircle(const Circle& c) { // c cannot be modified
[Link](); // OK: const method on const ref
[Link](2); // ERROR: non-const method on const ref
}

// POSITION 4: const return value — caller cannot modify the returned value
const double& getPi() { static const double pi=3.14159; return pi; }
getPi() = 3.0; // COMPILE ERROR: returned reference is const

■ Tip
A general rule: if a method does not change any data member, always mark it const. If a function
parameter is a class object you only need to read, always pass it as const&. This prevents bugs
and makes code self-documenting.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 29

Chapter 13

Object Lifetime and Memory — Where Do


Objects Live?
13.1 Stack objects — automatic lifetime
void foo() {
// Stack objects — created automatically, destroyed automatically:
int x = 5; // primitive on stack
std::string s = "hello"; // object on stack
UnitConverter<T,D> conv(...); // OpenLB object on stack

// ... use x, s, conv ...

} // <- ALL of x, s, conv destroyed HERE automatically (RAII)

// In [Link] main():
int main() {
const UnitConverter<T,D> converter(...); // stack — auto destroyed
SuperGeometry<T,2> superGeometry(...); // stack — auto destroyed
SuperLattice<T,D> sLattice(...); // stack — auto destroyed
// ...
return 0; // all three destructors run here, reverse order
}

13.2 Heap objects — manual lifetime (new/delete)


// Heap objects — you control lifetime with new/delete:
BankAccount* acc = new BankAccount("Alice", 1000);
// acc is a POINTER. The object lives on the HEAP.
// It will NOT be destroyed when 'acc' goes out of scope!

acc->deposit(200); // use arrow operator for pointer

delete acc; // YOU must call delete — otherwise MEMORY LEAK


acc = nullptr; // good practice: null the pointer after delete

// Modern C++ uses smart pointers to avoid manual delete:


#include <memory>
auto acc2 = std::make_unique<BankAccount>("Bob", 500);
acc2->deposit(100); // use normally
// No delete needed! unique_ptr destructor calls delete automatically

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 30

■ Tip
In [Link], you never see raw new/delete — OpenLB manages its own memory internally
using smart pointers and RAII. You create objects on the stack and the library handles the rest.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 31

Chapter 14

Every Class in [Link] — The


Complete Analysis
This chapter explains every class used in [Link]. For each class: what kind of class it is, what
data it holds, what methods it provides, and exactly what role it plays in the simulation.

14.1 UnitConverter<T, DESCRIPTOR>


const UnitConverter<T,DESCRIPTOR> converter(
(T) L, // physDeltaX = 0.01 m
(T) CFL*L/0.2, // physDeltaT = 0.0025 s
(T) 2.0*radiusCylinder, // charPhysLength = 0.1 m (diameter)
(T) 0.2, // charPhysVelocity = 0.2 m/s
(T) 0.2*2.*radiusCylinder/Re, // physViscosity = 0.001 m^2/s
(T) 1.0 // physDensity = 1 kg/m^3
);
[Link](); // logs all derived quantities

Property Detail

Kind Template class (class template)

Data members 6 const T values: physDeltaX, physDeltaT, charPhysLength, charPhysVelocity,


physViscosity, physDensity

Key methods getLatticeTime(), getPhysTime(), getCharLatticeVelocity(),


getLatticeRelaxationFrequency(), print()

All methods const — it is declared const, so no modification is allowed

Purpose Converts between SI units and LBM lattice units. Central reference for all unit
conversions.

Constructed Once, in main(). Passed by const& everywhere — efficient and safe.

14.2 SuperGeometry<T, 2>


SuperGeometry<T,2> superGeometry(cuboidDecomposition, loadBalancer);
prepareGeometry(converter, superGeometry, circle);
// prepareGeometry calls:
// [Link](0, 2);
// [Link](2, 1, {1,1});
// [Link](2, 3, 1, inflow);
// [Link](2, 4, 1, outflow);

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 32

// [Link](1, 5, circle);
// [Link]();
// [Link]();
// [Link]();

Property Detail

Kind Template class with type param T and non-type param 2 (dimensions)

Data members A distributed array of integers (the material numbers), one per lattice cell. For
220x42 grid = 9240 cells.

Key methods rename() — change material tags; clean() — remove isolated cells;
checkForErrors() — validate; print() — statistics

Purpose The geometry description layer. Tells the lattice WHERE walls are, where
inlet/outlet are, where the cylinder is.

Constructed In main() after CuboidDecomposition and LoadBalancer. Modified by


prepareGeometry().

Destroyed Automatically at end of main(). Destructor frees distributed geometry data.

14.3 SuperLattice<T, DESCRIPTOR>


SuperLattice<T,DESCRIPTOR> sLattice(superGeometry);
prepareLattice(sLattice, converter, superGeometry, circle);
// prepareLattice calls:
// [Link]<BGKdynamics>(superGeometry, 1);
// [Link](superGeometry, 1, rhoF, uF);
// [Link](superGeometry, 1, rhoF, uF);
// [Link]<OMEGA>(omega);
// [Link]();
// Main loop calls:
// [Link]();
// [Link](...);

Property Detail

Kind Template class: T=precision, DESCRIPTOR=lattice type (determines how many f


values per cell)

Data members For D2Q9: 9 doubles per cell x 9240 cells = ~83,000 doubles (~660 KB). Plus
boundary data, dynamics pointers.

Key methods collideAndStream() — the main LBM step; defineDynamics() — assign collision
rules; defineRhoU() / iniEquilibrium() — set initial state; setParameter() — set
omega

Purpose The heart of the simulation. Stores all distribution functions f_i. Executes the LBM
algorithm.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 33

Constructed In main() taking superGeometry to know which cells exist.

GPU support setProcessingContext() moves data between CPU RAM and GPU VRAM.

14.4 IndicatorF2D<T>, IndicatorCuboid2D<T>, IndicatorCircle2D<T>


// In main():
Vector<T,2> center{centerCylinderX, centerCylinderY};
IndicatorCircle2D<T> circle(center, radiusCylinder);

// In prepareGeometry() body:
IndicatorCuboid2D<T> inflow(extend, origin); // inlet strip rectangle
IndicatorCuboid2D<T> outflow(extend, origin); // outlet strip rectangle

// In prepareGeometry() signature:
void prepareGeometry(..., IndicatorF2D<T>& circle) { // base class ref
[Link](1, 5, circle); // uses circle as a test function
}

Class Kind Key method Data held Purpose

IndicatorF2D<T> Abstract base operator()(point) Bounding box Interface: is point


class =0 inside?

IndicatorCuboid2D< Concrete derived operator()(point) origin[2], Rectangle region test


T> extend[2]

IndicatorCircle2D<T> Concrete derived operator()(point) centre[2], radius Circle region test

14.5 CuboidDecomposition2D<T> and HeuristicLoadBalancer<T>


// Decompose the full domain into sub-domains for parallel processing:
IndicatorCuboid2D<T> cuboid(extend, origin); // the full domain rectangle
CuboidDecomposition2D<T> cuboidDecomposition(
cuboid, // what to decompose
L, // minimum cuboid size
singleton::mpi().getSize() // how many pieces
);

// Assign pieces to MPI processes:


HeuristicLoadBalancer<T> loadBalancer(cuboidDecomposition);
// Uses a heuristic (greedy) algorithm to give each process equal work

Class Data held Purpose

CuboidDecomposition2D<T List of sub-rectangle boundaries Splits the 2.2x0.42m domain into N


> and sizes sub-domains, one per MPI rank

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 34

HeuristicLoadBalancer<T> Map: cuboid index → MPI rank Assigns cuboids to MPI processes
trying to balance work equally

14.6 AnalyticalConst2D<T,T> and Poiseuille2D<T> (Functors)


// Functor classes — objects that behave like functions

AnalyticalConst2D<T,T> rhoF(1); // returns 1.0 at every (x,y)


AnalyticalConst2D<T,T> uF(0, 0); // returns (0,0) at every (x,y)

// These ARE objects of a class. But they define operator():


// double density = rhoF(x, y); // calls operator() — returns 1.0

// Used to set initial conditions:


[Link](superGeometry, 1, rhoF, uF);
[Link](superGeometry, 1, rhoF, uF);

// Poiseuille2D: parabolic inlet profile functor


Poiseuille2D<T> poiseuilleU(superGeometry, 3, maxVelocity, distance2Wall);
// poiseuilleU(x, y) returns the correct velocity at point (x,y) on the inlet
[Link](superGeometry, 3, poiseuilleU);

Class Inherited from operator()(x,y) returns Purpose

AnalyticalConst2D<T,T> AnalyticalF2D (functor Constant value set at Uniform initial


base) construction conditions

Poiseuille2D<T> AnalyticalF2D (functor Parabolic velocity for point Inlet velocity


base) (x,y) on inlet profile

PolynomialStartScale<T, StartScale base Ramp fraction [0..1] at time t Smooth start-up


T> ramp

AnalyticalFfromSuperF2 AnalyticalF2D Interpolated field value at Query discrete


D<T> (x,y) fields at any point

14.7 SuperLatticePhysVelocity2D and SuperLatticePhysPressure2D


SuperLatticePhysVelocity2D<T,DESCRIPTOR> velocity(sLattice, converter);
SuperLatticePhysPressure2D<T,DESCRIPTOR> pressure(sLattice, converter);

[Link](velocity); // add to output writer


[Link](pressure);

// These are also FUNCTOR classes (inherit from SuperLatticeF2D)


// When evaluated at a cell, they convert raw f-populations
// to physical velocity [m/s] or pressure [Pa] using converter

// Used BOTH for file output AND for the pressure-drop measurement:
AnalyticalFfromSuperF2D<T> interpolatePressure(pressure, true);
T p1; interpolatePressure(&p1, point1); // pressure at upstream point

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 35

T p2; interpolatePressure(&p2, point2); // pressure at downstream point

Property SuperLatticePhysVelocity2D SuperLatticePhysPressure2D

Inherits from SuperLatticeF2D<T,D> SuperLatticeF2D<T,D>

References sLattice, converter sLattice, converter

Returns per cell 2D velocity vector [m/s] Scalar pressure [Pa]

Conversion u_lbm * (dx/dt) (rho_lbm - 1) * cs^2 * rho_phys *


dx^2/dt^2

Used for VTK output + visualisation VTK output + pressure-drop


measurement

14.8 SuperVTMwriter2D<T> and util::Timer<T>


// Output writer:
SuperVTMwriter2D<T> vtmWriter("cylinder2d");
[Link](); // create index file on first step
[Link](velocity); // register what to output
[Link](pressure);
[Link](iT); // write files for this time step

// Timer:
util::Timer<T> timer(iTmax, [Link]().getNvoxel());
[Link]();
// ... simulation loop ...
[Link](iT); // record current progress
[Link](); // print elapsed time, MLUPs (million lattice updates/s)
[Link]();
[Link](); // final performance report

Class Data members Purpose

SuperVTMwriter2D<T> File prefix, list of registered functors Writes VTK Multi-block files readable
by ParaView

util::Timer<T> Start time, iTmax, cell count, Measures wall-clock time, computes
history MLUPs performance metric

14.9 OstreamManager — the console output class


OstreamManager clout(std::cout, "getResults");

clout << "pressure1=" << p1;


clout << "; pressureDrop=" << pressureDrop << std::endl;
// Output: [getResults] pressure1=0.00312; pressureDrop=0.00205

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 36

// OstreamManager IS-A std::ostream (by inheritance)


// It wraps std::cout and prepends a prefix to each line
// In parallel (MPI) runs, it also prepends the process rank
// so you know which MPI process printed each line

// The << operator is overloaded in std::ostream and inherited:


// ostream& operator<<(int x);
// ostream& operator<<(double x);
// ostream& operator<<(const char* s);
// ... etc

14.10 Vector<T, 2> — the simple coordinate class


// In prepareGeometry and main():
Vector<T,2> extend(lengthX, lengthY); // size of domain
Vector<T,2> origin; // bottom-left corner
Vector<T,2> center{centerCylinderX, centerCylinderY};

// Index access with []:


extend[0] = 2.*L; // set X component
origin[0] = -L; // set X component of origin

// Vector<T,2> is a simple class holding exactly 2 values of type T.


// It overloads operator[] for element access.
// It is similar to std::array<T,2> but with OpenLB-specific methods.

14.11 BGKdynamics, BounceBack, InterpolatedVelocity,


InterpolatedPressure — Policy Classes
These are policy classes — they do not create objects that exist at runtime. Instead, they are passed as
template arguments to tell defineDynamics or boundary::set which algorithm to use. The compiler
generates different code for each policy:

// These are classes used AS TYPES (template arguments), not as objects:

[Link]<BGKdynamics>(superGeometry, 1);
// BGKdynamics: a class encoding the BGK collision algorithm.
// The template instantiation reads BGKdynamics::collide() and
// generates optimised code for that specific collision rule.

boundary::set<boundary::BounceBack>(sLattice, superGeometry, 2);


// BounceBack: a class encoding the reflection boundary rule.
// Its static constexpr members describe how populations are reflected.

boundary::set<boundary::InterpolatedVelocity>(sLattice, superGeometry, 3);


// InterpolatedVelocity: 2nd-order velocity boundary condition class.

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 37

boundary::set<boundary::InterpolatedPressure>(sLattice, superGeometry, 4);


// InterpolatedPressure: fixed-pressure (Dirichlet) boundary condition
class.

Policy class Algorithm Applied to material Physics

BGKdynamics BGK (Bhatnagar-Gross- 1 (fluid) f_i → f_i + omega*(f_eq


Krook) collision - f_i)

BounceBack Reflect populations back 2 (walls) No-slip: u_wall = 0

InterpolatedVelocity 2nd-order velocity BC 3 (inlet) Fixed velocity: Poiseuille


profile

InterpolatedPressure 2nd-order pressure BC 4 (outlet) Fixed pressure: p = 0

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 38

Chapter 15

The 10 Most Common Class Mistakes — and


How to Avoid Them
// MISTAKE 1: Missing semicolon after closing brace
class Dog { } // COMPILE ERROR: expected ';' after class definition
class Dog { }; // CORRECT

// MISTAKE 2: Calling a non-const method on a const reference


void info(const SuperGeometry<T,2>& sg) {
[Link](0, 1); // ERROR: rename() is non-const on const reference
[Link](); // OK if print() is a const method
}

// MISTAKE 3: Accessing private members from outside


class Circle { double radius; };
Circle c; [Link] = 5.0; // ERROR: radius is private (class default)

// MISTAKE 4: Forgetting to call the base constructor


class Dog : public Animal {
Dog() {} // ERROR if Animal has no default constructor
Dog() : Animal("Rex", 100) {} // CORRECT: call base ctor
};

// MISTAKE 5: Object slicing


Circle c(5.0, "red");
Shape s = c; // SLICES: copies only the Shape part, loses Circle data
Shape& r = c; // CORRECT: reference preserves the Circle

// MISTAKE 6: Forgetting virtual destructor in base class


class Base { ~Base(){} }; // non-virtual destructor
class Derived : public Base {};
Base* ptr = new Derived();
delete ptr; // Only calls ~Base() — ~Derived() never runs! Memory leak.

class Base { virtual ~Base(){} }; // CORRECT: virtual destructor

// MISTAKE 7: Using 'this' in constructor initialiser list order


class Bad {
int b;
int a; // declared AFTER b
public:
Bad(int x) : a(x), b(a) {} // UNDEFINED: a is initialised after b!
}; // Members initialise in DECLARATION order, not initialiser list order

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 39

// MISTAKE 8: const member without initialiser list


class Oops {
const int n;
public:
Oops(int x) { n = x; } // ERROR: const member must be in init list
Oops(int x) : n(x) {} // CORRECT
};

// MISTAKE 9: Multiple inheritance diamond problem (rare but confusing)


class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {}; // D has TWO copies of A — ambiguous!
// Solution: virtual inheritance (advanced — not in [Link])

// MISTAKE 10: Infinite recursion in constructor delegation


class Bad2 {
Bad2() : Bad2(0) {} // calls parameterised ctor
Bad2(int n) : Bad2() {}// calls default ctor -> infinite loop!
};

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 40

Chapter 16

Master Summary — All Class Concepts at a


Glance

C++ class

Data members Member functions Constructors & Access


(fields / attributes) (methods) Destructors Specifiers

Instance Static Regular const Static Default Param


Destructor public private protected
variables variables methods methods methods ctor ctor

Inheritance
Polymorphism
(is-a) (virtual)

Figure 2 — C++ class concept taxonomy tree

Concept Keyword/syntax Purpose Example in [Link]

Class definition class Name { }; Define a new type class BankAccount { };

Data member Type name; Store object's state SuperGeometry stores


material numbers

Static data member static Type name; Shared by all instances D2Q9 stores weight factors
statically

Member function RetType Define object behaviour [Link]()


method(args)

const method RetType f() const Promise not to modify All UnitConverter methods
object are const

Static method static RetType f() Callable without an singleton::mpi()


object

public public: Accessible from All OpenLB API methods


anywhere

private private: Accessible only from Internal OpenLB data arrays


within the class

protected protected: Accessible from within IndicatorF2D _myMin,


and derived classes _myMax

OpenLB Lattice-Boltzmann | [Link]


C++ Classes — Deep Dive Study Guide | [Link] Page 41

Default constructor Class() Create object with no —


arguments

Param constructor Class(args) Create object with UnitConverter(dx, dt, L, U,


arguments nu, rho)

Init list : m1(v1), m2(v2) Initialise members UnitConverter const


efficiently in ctor members

Destructor ~Class() Automatic cleanup when SuperLattice frees GPU


object dies memory

Dot operator [Link] Access member of an [Link]()


object

Arrow operator ptr->member Access member via Internal OpenLB


pointer implementation

Inheritance : public Base Derive new class from IndicatorCircle2D : public


existing one IndicatorF2D

virtual function virtual RetType f() Enable runtime IndicatorF2D::operator() = 0


polymorphism

pure virtual =0 Force derived class to IndicatorF2D is abstract


override

override override Confirm this overrides a IndicatorCircle2D::operator()


virtual override

Abstract class has = 0 methods Cannot be instantiated IndicatorF2D — only


directly derived classes used

Functor operator()(args) Object callable like a AnalyticalConst2D,


function Poiseuille2D

this pointer this Pointer to the current Used inside OpenLB for
object chaining

— End of C++ Classes Deep Dive —

OpenLB Lattice-Boltzmann | [Link]

You might also like