The content is gathered from chatgpt
Struct vs. Class #
struct and class are interchangeable except for defaults:
structmembers and base classes arepublicby default.classmembers and base classes areprivateby default.- Otherwise they behave identically (constructors, inheritance, virtuals, templates, etc.).
- Style: prefer
structfor plain-data / public interfaces andclassfor encapsulation.
The snippet shows the default member and inheritance access differences and how to make them explicit.
// cpp
#include <iostream>
struct S {
int x; // public by default
};
class C {
int x; // private by default
public:
C(int v) : x(v) {}
int get() const { return x; }
};
struct Base {};
struct SDerived : Base { /* public inheritance by default */ };
class CDerived : Base { /* private inheritance by default */ };
int main() {
S s{1};
std::cout << s.x << "\n"; // OK: public
C c(2);
std::cout << c.get() << "\n"; // access via public method
// SDerived sd; // behaves like public inheritance
// CDerived cd; // behaves like private inheritance
return 0;
}
Public inheritance #
Public inheritance means the derived type preserves the base type’s public interface and models an “is-a” relationship. Concretely:
- Members: public and protected members of the base remain public and protected in the derived class.
- Polymorphism: you can use a
Derived*orDerived&where aBase*/Base&is expected, and virtual functions work through base pointers. - Semantics: expresses that
Derived“is a”Base. structmakes members public by default;
Example:
// C++
struct Base {
virtual void f() = 0; // public in Base
protected:
int p; // protected in Base
};
struct PublicDerived : public Base {
void f() override { p = 1; } // p still protected, f still public
};
struct PrivateDerived : private Base {
void f() override {} // Base::f becomes private to users of PrivateDerived
};
void takeBase(Base* b) { b->f(); }
int main() {
PublicDerived pd;
takeBase(&pd); // OK: public inheritance allows substitution
// PrivateDerived pr;
// takeBase(&pr); // ERROR: cannot convert due to private inheritance
}
Private inheritance #
Private inheritance means a derived class inherits implementation from a base class but hides the base’s public/protected interface from outside code. It is used to express “implemented in terms of” rather than “is-a”.
Key points:
- Public and protected members of the base become private in the derived class (outside users cannot access them).
- Automatic conversion from
Derived*toBase*is not allowed for outside code (the base subobject is privately accessible). Only members and friends ofDerivedcan do that conversion. - Virtual dispatch still works if you have a
Base*to theDerivedobject, but external code cannot get aBase*from aDerived*when inheritance is private. - You can selectively expose base methods via
usingor by writing forwarding wrappers.
Example:
- Shows private inheritance, attempt to pass
Derivedto a function takingBase*fails outside. Derivedcan callBasemembers internally.using Base::foo;underpublic:exposesfooto users.
// cpp
#include <iostream>
struct Base {
virtual ~Base() = default;
void foo() { std::cout << "Base::foo\n"; }
virtual void v() { std::cout << "Base::v\n"; }
};
struct Derived : private Base { // private inheritance
public:
// expose foo() as public in Derived
using Base::foo;
// override virtual (still valid)
void v() override { std::cout << "Derived::v\n"; }
void callBase() {
// Derived code can access Base members
Base::foo();
}
};
void takesBase(Base* b) {
b->v();
}
int main() {
Derived d;
d.foo(); // OK: exposed via using-declaration
d.callBase(); // OK: Derived can access Base::foo internally
// takesBase(&d); // ERROR: cannot convert Derived* to Base* here because
// inheritance is private
// But inside Derived (or its friends) conversion is allowed:
// static_cast<Base*>(&d) is allowed only in Derived/friend scope.
return 0;
}