Question

Class vs Struct in C++: When to Use Each

cppoopclassstructooad

Question

In C++, in which situations is it more appropriate to use a struct instead of a class, and when should you prefer a class instead?

What practical differences matter when designing types in real programs?

Short Answer

By the end of this page, you will understand the technical difference between struct and class in C++, the common coding conventions around each, and how to choose the right one for data-focused types versus behavior-focused types.

Concept

In C++, struct and class are almost the same language feature. The main technical difference is the default access level:

  • In a struct, members are public by default.
  • In a class, members are private by default.

There is one more matching default rule:

  • struct uses public inheritance by default.
  • class uses private inheritance by default.

Example:

struct Point {
    int x; // public by default
    int y; // public by default
};

class BankAccount {
    double balance; // private by default
};

So why do both exist if they are so similar?

Because programmers use them to communicate intent.

A common convention is:

  • Use struct for simple data objects where members are meant to be openly accessible.
  • Use class for types that hide internal state and provide behavior through member functions.

This matters because code is read much more often than it is written. Choosing struct or class helps other developers quickly understand whether a type is mainly a plain data holder or an encapsulated object with rules.

Why this matters in real programming

When designing a type, you are deciding:

  • Should users access fields directly?
  • Should data be protected behind methods?
  • Does the type enforce rules or invariants?
  • Is the type just a lightweight grouping of values?

If a type has important rules, such as "balance must never be negative" or "age must be valid," a class is usually better because it encourages encapsulation.

If a type simply groups related values like coordinates, color channels, or configuration data, a struct is often clearer and simpler.

Mental Model

Think of a struct as a clear plastic container and a class as a locked box with buttons on the outside.

  • With a struct, people can see and access the contents directly.
  • With a class, the contents are hidden, and people interact with it through approved controls.

Neither is automatically better. The choice depends on whether direct access is safe and useful.

If the object is just holding values, the clear container is convenient. If the object needs to protect its state or enforce rules, the locked box is safer.

Take Quiz

Syntax and Examples

Basic syntax

struct Person {
    std::string name;
    int age;
};

class BankAccount {
    double balance;

public:
    BankAccount(double initialBalance) : balance(initialBalance) {}

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

    double getBalance() const {
        return balance;
    }
};

Example 1: Use struct for plain data

#include <iostream>
#include <string>

struct UserProfile {
    std::string username;
    int score;
};

int main() {
    UserProfile user{"alice", 120};
    std::cout << user.username << " has score " << user.score << '\n';
}

This is a good struct because:

  • It groups related values.
  • Direct field access is fine.
  • There is no complex rule to protect.

Example 2: Use class for encapsulation

#include <iostream>

class Temperature {
    double celsius;

public:
    Temperature(double value) : celsius(value) {}

    void setCelsius(double value) {
        celsius = value;
    }

    double getCelsius() const {
        return celsius;
    }

    double toFahrenheit() const {
        return (celsius * 9.0 / 5.0) + 32.0;
    }
};

int main() {
    Temperature temp(25.0);
    std::cout << temp.toFahrenheit() << '\n';
}

This is a good class because:

  • It exposes behavior.
  • Its internal representation can change later.
  • Users interact through methods instead of raw member access.

Important note

A struct can still have:

  • constructors
  • methods
  • private members
  • inheritance
  • operators

Example:

struct Rectangle {
    double width;
    double height;

    double area() const {
        return width * height;
    }
};

So the choice is mostly about readability and design intent, not capability.

Step by Step Execution

Consider this example:

#include <iostream>

struct Point {
    int x;
    int y;
};

class Counter {
    int value;

public:
    Counter() : value(0) {}

    void increment() {
        value++;
    }

    int getValue() const {
        return value;
    }
};

int main() {
    Point p{3, 4};
    std::cout << p.x << ", " << p.y << '\n';

    Counter c;
    c.increment();
    c.increment();
    std::cout << c.getValue() << '\n';
}

What happens step by step

  1. Point is defined as a struct.

    • x and y are public by default.
  2. Counter is defined as a class.

    • value is private by default.
    • Only public methods can access it from outside.
  3. In main, Point p{3, 4}; creates a point.

    • p.x becomes 3
    • p.y becomes 4
  4. std::cout << p.x << ", " << p.y works.

    • Direct access is allowed because Point members are public.
  5. Counter c; creates a counter.

    • The constructor sets value to 0.
  6. c.increment(); runs twice.

    • First call: value becomes 1
    • Second call: value becomes 2
  7. c.getValue() returns 2.

Key takeaway

The struct exposes data directly. The class protects data and exposes operations.

Real World Use Cases

struct and class both appear often in real C++ programs, but usually for different design purposes.

Common uses for struct

  • Geometry data: points, rectangles, vectors
  • Configuration objects: settings loaded from a file
  • DTO-style objects: data transfer between modules
  • Simple records: log entries, sensor readings, parsed values
  • Public aggregate data: values that are naturally open

Example:

struct AppConfig {
    std::string host;
    int port;
    bool debug;
};

Common uses for class

  • Objects with invariants: account balances, validated IDs
  • Business logic types: orders, carts, services
  • Resource management: file wrappers, sockets, mutex guards
  • APIs with controlled usage: types with clear public methods
  • Libraries: types that may evolve without exposing internals

Example:

class FileLogger {
    std::string path;

public:
    explicit FileLogger(const std::string& filePath) : path(filePath) {}
    void log(const std::string& message);
};

If changing a field directly could break the object, prefer a class.

Take Quiz

Real Codebase Usage

In real codebases, the choice is often based on convention, maintainability, and encapsulation, not on language limitations.

Common team conventions

Many C++ teams follow this rule of thumb:

  • struct = passive data
  • class = active object with rules and behavior

This makes large codebases easier to scan.

Patterns developers use

1. Data carriers with struct

struct HttpResponse {
    int statusCode;
    std::string body;
    std::string contentType;
};

This is easy to create, return, and inspect.

2. Validation and invariants with class

class Age {
    int value;

public:
    explicit Age(int v) {
        if (v < 0) {
            throw std::invalid_argument("Age cannot be negative");
        }
        value = v;
    }

    int get() const {
        return value;
    }
};

The class prevents invalid state.

3. Guarding internal changes

A class lets developers change implementation later without changing the public interface.

For example, this:

class Timer {
public:
    void start();
    void stop();
    double elapsedSeconds() const;
};

can later gain internal fields without affecting calling code.

4. Readable APIs

When other developers see a class, they usually expect:

  • hidden details
  • controlled operations
  • a stable interface

When they see a struct, they usually expect:

  • public members
  • straightforward data access
  • little or no hidden logic

Practical guideline

If your type mainly answers "What values belong together?" use a struct. If it mainly answers "What operations and guarantees does this object provide?" use a class.

Common Mistakes

1. Thinking struct is only for C-style code

In C++, struct is a full-featured type. It can have methods, constructors, operators, and private members.

struct Timer {
private:
    int seconds;

public:
    Timer() : seconds(0) {}
    void tick() { seconds++; }
};

2. Assuming class and struct behave completely differently

They do not. The biggest built-in difference is the default access and default inheritance.

3. Exposing data that should be protected

Broken design:

class BankAccount {
public:
    double balance;
};

This lets anyone set balance to an invalid value.

Better:

class BankAccount {
    double balance;

public:
    explicit BankAccount(double initialBalance) : balance(initialBalance) {}

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

    double getBalance() const {
        return balance;
    }
};

4. Hiding simple data for no reason

Sometimes beginners create getters and setters for every tiny data object even when direct access would be clearer.

Overcomplicated:

class Point {
    int x;
    int y;

public:
    Point(int xValue, int yValue) : x(xValue), y(yValue) {}
    int getX() const { return x; }
    int getY() const { return y; }
};

Simpler:

struct Point {
    int x;
    int y;
};

5. Forgetting the inheritance default

struct Base {};
struct Derived : Base {}; // public inheritance by default

class Base2 {};
class Derived2 : Base2 {}; // private inheritance by default

This can surprise beginners. Be explicit when possible:

class Derived2 : public Base2 {};

6. Using naming style as the only rule

Do not choose struct or class just because of a naming habit. Choose based on whether the type should expose data or protect it.

Comparisons

Topicstructclass
Default member accesspublicprivate
Default inheritancepublicprivate
Can have methods?YesYes
Can have constructors?YesYes
Can have private members?YesYes
Typical usePlain data, simple recordsEncapsulation, behavior, invariants
Signals to readersOpen dataControlled interface

struct vs class in practice

SituationBetter choiceWhy
Coordinate with x and ystructSimple public data
Bank account with rulesclassMust protect state
Parsed config valuesstructEasy to read and assign
Resource-owning typeclassStrong interface and safety

Is one more powerful?

No. In C++, they are nearly identical in power. The difference is mainly about defaults and design intent.

Take Quiz

Cheat Sheet

  • struct and class are almost the same in C++.
  • Main difference:
    • struct members are public by default
    • class members are private by default
  • Inheritance default:
    • struct Derived : Base means public inheritance
    • class Derived : Base means private inheritance

Use struct when

  • the type is mainly a bundle of related values
  • direct access is acceptable
  • there are few or no invariants to protect
  • you want a lightweight data object

Use class when

  • internal state should be hidden
  • the object must enforce rules
  • you want a clear public API
  • the implementation may change later

Quick examples

struct Point {
    int x;
    int y;
};

class Counter {
    int value;
public:
    Counter() : value(0) {}
    void increment() { value++; }
    int getValue() const { return value; }
};

Rule of thumb

  • struct = data-oriented
  • class = behavior-oriented

Edge case

A struct can still have private members and methods. A class can still have public data. The choice is about clarity, not strict capability.

FAQ

Is there any real difference between struct and class in C++?

Yes, but it is small. The main difference is the default access level and default inheritance. Otherwise, they support almost the same features.

Should I always use class in modern C++?

No. struct is still very useful for simple data types and is common in modern C++ code.

Is struct less object-oriented than class?

No. A struct can have methods, constructors, operators, and private members. It is still a full C++ type.

Why do many examples use struct for small data types?

Because public fields are often the clearest design for simple records like points, colors, or settings.

When should I switch from a struct to a class?

Switch when the type starts needing validation, hidden state, controlled updates, or a more stable public interface.

Can a struct have private members?

Yes.

struct Example {
private:
    int secret;
};

Which one is faster: struct or class?

Neither is inherently faster. Performance depends on the actual design and implementation, not the keyword used.

Take Quiz

Mini Project

Description

Create a small C++ program that models two different kinds of types: a simple public data record and an encapsulated object with rules. This project demonstrates why struct is a good fit for plain data, while class is better when you need to protect state and control how it changes.

Goal

Build a program that uses a struct for a public user profile and a class for a bank account with safe deposit and withdrawal behavior.

Requirements

  1. Create a struct named UserProfile with public fields for name and age.
  2. Create a class named BankAccount with a private balance.
  3. Add public methods to deposit money, withdraw money, and read the current balance.
  4. Prevent withdrawals that would make the balance negative.
  5. In main(), create both types and print their data/results.
Take Quiz

Keep learning

Related questions

View more