class vs struct, Access Specifiers & this Pointer
In C++, `class` and `struct` are nearly identical — the only difference is the **default access**: `struct` defaults to `public`, `class` defaults to `private`. By convention: use `struct` for plain data aggregates with all-public members; use `class` for types with invariants (private state and public interface). The `this` pointer is an implicit parameter in every non-static member function — it points to the object on which the method is called.
class vs struct, Access Specifiers & this Pointer
#include <iostream>
#include <string>
// ── struct — plain data aggregate (all public) ─────────────
struct Point {
double x, y; // public by default
// No invariants to enforce — struct is appropriate
double length() const {
return std::sqrt(x*x + y*y);
}
};
// ── class — enforces invariants via private state ──────────
class BankAccount {
// private by default (no specifier needed at top)
std::string owner_;
double balance_; // trailing _ convention for private
// Only the member functions can access these
public:
// Public interface
BankAccount(std::string name, double initial_balance);
void deposit(double amount);
bool withdraw(double amount);
double balance() const { return balance_; } // getter — returns copy
const std::string& owner() const { return owner_; } // returns const ref
protected:
// Accessible in this class AND derived classes
void reset_balance() { balance_ = 0.0; } // for subclass use
// 'private' again would be: private:
public:
void print() const;
};
// ── this pointer — implicit pointer to current object ─────
void BankAccount::print() const {
// 'this' has type 'const BankAccount*' in a const method
std::cout << "Account owner: " << this->owner_ // same as owner_
<< ", balance: $" << this->balance_ << "
"; // same as balance_
}
BankAccount::BankAccount(std::string name, double initial_balance)
: owner_(std::move(name)) // member initialiser list (next topic)
, balance_(initial_balance)
{}
void BankAccount::deposit(double amount) {
if (amount <= 0) return;
balance_ += amount;
}
bool BankAccount::withdraw(double amount) {
if (amount <= 0 || amount > balance_) return false;
balance_ -= amount;
return true;
}
int main() {
// struct — direct member access
Point p{3.0, 4.0};
std::cout << "Length: " << p.length() << "
"; // 5.0
p.x = 6.0; // OK — public
// class — private: direct member access blocked
BankAccount acc{"Alice", 1000.0};
acc.deposit(500.0);
acc.withdraw(200.0);
// acc.balance_ = 999.0; ← compile error: balance_ is private
std::cout << "Balance: " << acc.balance() << "
"; // 1300.0
acc.print();
return 0;
}Common Mistakes
- Accessing `this` in a static member function — static methods have no `this` pointer (they're not associated with an instance). Calling `this->member` in a static function is a compile error.
- Unnecessary `this->` everywhere — in member functions, `member` and `this->member` are identical. Use `this->` only to disambiguate (e.g., when a parameter has the same name as a member) or for clarity in `return *this` chains.
- Using struct when invariants are needed — if a type needs to maintain constraints (balance must be ≥ 0, name must not be empty), use `class` with private members and public mutators that validate. A `struct` with public members can be modified into an invalid state by anyone.
Tip
Tip
Practice class vs struct Access Specifiers this Pointer in small, isolated examples before integrating into larger projects. Breaking concepts into small experiments builds genuine understanding faster than reading alone.
The four pillars of Object-Oriented Programming in C++
Practice Task
Note
Practice Task — (1) Write a working example of class vs struct Access Specifiers this Pointer from scratch without looking at notes. (2) Modify it to handle an edge case (empty input, null value, or error state). (3) Share your solution in the Priygop community for feedback.
Quick Quiz
Common Mistake
Warning
A common mistake with class vs struct Access Specifiers this Pointer is skipping edge case testing — empty inputs, null values, and unexpected data types. Always validate boundary conditions to write robust, production-ready cpp code.
Key Takeaways
- In C++, `class` and `struct` are nearly identical — the only difference is the **default access**: `struct` defaults to `public`, `class` defaults to `private`.
- Accessing `this` in a static member function — static methods have no `this` pointer (they're not associated with an instance). Calling `this->member` in a static function is a compile error.
- Unnecessary `this->` everywhere — in member functions, `member` and `this->member` are identical. Use `this->` only to disambiguate (e.g., when a parameter has the same name as a member) or for clarity in `return *this` chains.
- Using struct when invariants are needed — if a type needs to maintain constraints (balance must be ≥ 0, name must not be empty), use `class` with private members and public mutators that validate. A `struct` with public members can be modified into an invalid state by anyone.