C++ Programming · Lesson 3 of 9 · Updated ·
Classes and Objects in C++ — Constructors, Destructors, this and static
A class bundles data and the functions that work on it. This is where C++ becomes object-oriented (see the general OOP Concepts subject for the theory).
1. A first class
#include <iostream>
#include <string>
using namespace std;
class BankAccount {
private:
string owner;
double balance;
public:
BankAccount(const string &name, double opening) // constructor
: owner(name), balance(opening) {} // initializer list
void deposit(double amount) {
if (amount > 0) balance += amount;
}
bool withdraw(double amount) {
if (amount > balance) return false;
balance -= amount;
return true;
}
double get() const { return balance; } // const: doesn't change the object
};
int main() {
BankAccount acc("Asha", 1000);
acc.deposit(500);
cout << acc.withdraw(2000) << " " << acc.withdraw(300) << " " << acc.get() << "\n";
return 0;
}
0 1 1200
privatemembers are accessible only inside the class;publicmembers form its interface. (protectedis for subclasses — next lessons.)- In a
class, members are private by default; in astruct, public by default. That's the only difference. acc.balance = -5;would be a compile error — encapsulation enforced by the compiler.
2. Constructors and the initializer list
- A constructor has the class's name and no return type; it runs when an object is created.
- The initializer list (
: owner(name), balance(opening)) sets members directly — required forconstmembers and references, and more efficient. - If you write no constructor, C++ gives a default one. Once you write any, the default disappears unless you add
ClassName() = default;.
3. Destructors
#include <iostream>
using namespace std;
class Logger {
int id;
public:
Logger(int i) : id(i) { cout << "open " << id << "\n"; }
~Logger() { cout << "close " << id << "\n"; } // destructor
};
int main() {
Logger a(1);
{
Logger b(2);
} // b is destroyed here
cout << "end of main\n";
return 0;
} // a is destroyed here
open 1
open 2
close 2
end of main
close 1
The destructor (~ClassName) runs automatically when an object goes out of scope — perfect for releasing files, memory and locks (the RAII idea, covered later).
4. The this pointer
Inside a member function, this points to the current object. It's useful when a parameter has the same name as a member, and to return the object itself for chaining:
#include <iostream>
using namespace std;
class Counter {
int value = 0;
public:
Counter &add(int n) { this->value += n; return *this; }
int get() const { return value; }
};
int main() {
Counter c;
c.add(5).add(10).add(-3);
cout << c.get() << "\n";
return 0;
}
12
5. static members
A static data member is shared by all objects of the class; a static function can be called without an object.
#include <iostream>
using namespace std;
class Student {
public:
static int count;
Student() { count++; }
static int total() { return count; }
};
int Student::count = 0; // define it once, outside the class
int main() {
Student a, b, c;
cout << Student::total() << "\n";
return 0;
}
3
Common mistakes
- Forgetting the semicolon after the class's closing brace
};. - Not marking getters
const, so they can't be called on const objects. - Declaring a static member but never defining it outside the class (a linker error).
Quick recap
- class = private data + public interface; class defaults to private, struct to public.
- Constructors (use initializer lists) and destructors (
~, automatic cleanup). this= the current object; return*thisfor chaining.staticmembers belong to the class;constmethods promise not to modify.