
#include<iostream>
class Base {
public:
void foo () { std::cout << "Calls Base::foo()\n"; }
void bar () { std::cout << "Calls Base::bar()\n"; }
};
class Derived : private Base {
public:
// Exempting Base::foo()
using Base::foo;
};
int main() {
Derived d;
d.foo();
// d.bar(); // Error
return 0;
}
#include<iostream>
class Base {
public:
Base( int m, int n ) : _m(m), _n(n){}
void foo () { std::cout << "Calls Base::foo()\n"; }
void bar () { std::cout << "Calls Base::bar()\n"; }
protected:
int _m;
private:
int _n;
};
class Derived : private Base {
public:
// Exempt Base::foo()
using Base::foo;
Derived( int m, int n ) : Base(m, n) {}
protected:
using Base::_m;
private:
// using Base::_n; // Error
};
class Derived2 : public Derived {
public:
Derived2(int m, int n) : Derived(m, n) {}
void show_m(){
std::cout << "m = " << _m << "\n";
}
};
int main() {
Derived2 d2(1, 2);
d2.show_m(); // m = 2
return 0;
}
The derived class can only restore the inherited member to its original access level. The access level cannot be made either more or less restrictive than the level originally specified within the base class.
#include <iostream>
#include <string>
// Public interface
class Shape {
public:
virtual void draw() const = 0; // Pure virtual
virtual ~Shape() {}
};
// Private implementation
class Logger {
protected:
void log(const std::string& msg) const {
std::cout << "[LOG]: " << msg << std::endl;
}
};
// Derived class uses both
class Circle : public Shape, private Logger {
public:
void draw() const override {
log("Drawing a circle"); // Use Logger internally
std::cout << "Circle is drawn." << std::endl;
}
};
int main() {
Circle c;
c.draw(); // Allowed: draw() is public
// c.log("test"); // Error: 'log' is private through inheritance
return 0;
}
| Inheritance Type | Rule of Thumb | Use Case |
|---|---|---|
public |
Use when you want to expose the base class’s public interface as part of the derived class. | “is-a” relationship: class Dog : public Animal |
protected |
Rarely used. Use when only derived classes should access base members, but not clients. | Internal derivation where public interface is not exposed. |
private |
Use when inheritance is purely an implementation detail, not visible to the client. | “implemented-in-terms-of”: e.g., stack implemented via vector: class Stack : private std::vector<T> |
| Composition Type | Rule of Thumb | Use Case |
|---|---|---|
| by value | Use when the composed object is always required and has the same lifetime. | Car has Engine (always has one) |
| by reference | Use when the composed object is shared, externally owned, and never null. | Injecting dependencies (e.g., reference to a logger) |
| by pointer | Use when the composed object is optional, polymorphic, or shared/owned dynamically. | Optional or changeable behavior: std::unique_ptr<Strategy> |