Constructors & Destructors
A constructor is a special member function that runs automatically the moment an object is created, letting you guarantee it starts out fully and correctly initialized. Its counterpart, the destructor, runs automatically when an object's lifetime ends — the foundation of a C++ idiom called RAII that ties resource cleanup directly to an object going out of scope.
A constructor
A constructor has the same name as the class and no return type. This one requires an owner and a starting balance to be supplied at creation time, so there's no way to end up with an account in a half-initialized state:
#include <iostream> #include <string> class BankAccount { public: std::string owner; double balance; BankAccount(std::string ownerName, double startingBalance) { owner = ownerName; balance = startingBalance; std::cout << "Account created for " << owner << std::endl; } }; int main() { BankAccount account("Jamie", 100); std::cout << account.owner << ": " << account.balance << std::endl; return 0; }
Account created for Jamie Jamie: 100
BankAccount account("Jamie", 100) calls the constructor immediately as the object is declared — there's no separate setBalance step to remember, and no way to construct a BankAccount at all without providing both arguments.
Constructor overloading and default values
Like any function, a constructor can be overloaded, or given default parameter values, to support more than one way of creating an object:
#include <iostream> #include <string> class BankAccount { public: std::string owner; double balance; BankAccount(std::string ownerName, double startingBalance = 0) { owner = ownerName; balance = startingBalance; } }; int main() { BankAccount account1("Jamie", 250); BankAccount account2("Sasha"); std::cout << account1.owner << ": " << account1.balance << std::endl; std::cout << account2.owner << ": " << account2.balance << std::endl; return 0; }
Jamie: 250 Sasha: 0
account2 is created with just an owner name, and startingBalance falls back to its default of 0 — the exact same default-argument rule from the Functions lesson applies to constructors.
Destructors and RAII
A destructor is named ~ClassName, takes no arguments, and runs automatically the instant an object's lifetime ends — for a local variable, that's when it goes out of scope:
#include <iostream> #include <string> class Logger { public: std::string name; Logger(std::string loggerName) { name = loggerName; std::cout << "[open] " << name << std::endl; } ~Logger() { std::cout << "[closed] " << name << std::endl; } }; int main() { std::cout << "Starting work..." << std::endl; { Logger log("session-1"); std::cout << "Doing work..." << std::endl; } std::cout << "Work finished." << std::endl; return 0; }
Starting work... [open] session-1 Doing work... [closed] session-1 Work finished.
log is declared inside the inner { } block, so its destructor runs automatically the moment execution reaches that block's closing brace — no explicit "close" call needed. This is RAII (Resource Acquisition Is Initialization): tie a resource's cleanup to an object's destructor, and it's guaranteed to run whenever that object goes out of scope, even if the surrounding code exits early or throws an exception.