Production-grade skill for Object-Oriented Programming in C++. Covers classes, inheritance, polymorphism, encapsulation, SOLID principles, and design patterns.
Provides C++ OOP expertise covering classes, inheritance, polymorphism, encapsulation, SOLID principles, and design patterns with production-ready code examples.
/plugin marketplace add pluginagentmarketplace/custom-plugin-cpp/plugin install cpp@pluginagentmarketplace-cppThis skill inherits all available tools. When active, it can use any tool Claude has access to.
assets/config.yamlassets/schema.jsonreferences/GUIDE.mdreferences/PATTERNS.mdscripts/validate.pyProduction-Grade Learning Skill | Object-Oriented Design
Master C++ OOP concepts and industry-standard design patterns.
class BankAccount {
private:
std::string id_;
double balance_{0.0}; // Default member init
public:
explicit BankAccount(std::string id) : id_(std::move(id)) {}
// Read-only access
[[nodiscard]] double balance() const { return balance_; }
[[nodiscard]] const std::string& id() const { return id_; }
// Controlled mutation with validation
void deposit(double amount) {
if (amount <= 0) {
throw std::invalid_argument("Amount must be positive");
}
balance_ += amount;
}
bool withdraw(double amount) {
if (amount <= 0 || amount > balance_) return false;
balance_ -= amount;
return true;
}
};
// Abstract base class
class Shape {
protected:
std::string name_;
public:
explicit Shape(std::string name) : name_(std::move(name)) {}
virtual ~Shape() = default; // ALWAYS virtual destructor!
// Pure virtual functions (interface)
[[nodiscard]] virtual double area() const = 0;
[[nodiscard]] virtual double perimeter() const = 0;
// Non-virtual (shared behavior)
[[nodiscard]] const std::string& name() const { return name_; }
};
class Circle final : public Shape { // final prevents further inheritance
double radius_;
public:
explicit Circle(double r) : Shape("Circle"), radius_(r) {}
[[nodiscard]] double area() const override {
return std::numbers::pi * radius_ * radius_;
}
[[nodiscard]] double perimeter() const override {
return 2 * std::numbers::pi * radius_;
}
};
// Runtime polymorphism via virtual functions
void printShape(const Shape& shape) {
std::cout << shape.name() << ": area = " << shape.area() << "\n";
}
// Usage - same function, different behavior
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Circle>(5.0));
shapes.push_back(std::make_unique<Rectangle>(3.0, 4.0));
for (const auto& shape : shapes) {
printShape(*shape); // Polymorphic dispatch
}
// Pure interface (all pure virtual)
class ILogger {
public:
virtual ~ILogger() = default;
virtual void log(std::string_view message) = 0;
virtual void setLevel(int level) = 0;
};
// Multiple implementations
class ConsoleLogger : public ILogger {
public:
void log(std::string_view message) override {
std::cout << "[LOG] " << message << "\n";
}
void setLevel(int) override { }
};
class FileLogger : public ILogger {
std::ofstream file_;
public:
explicit FileLogger(const std::string& path) : file_(path) {}
void log(std::string_view message) override {
file_ << message << "\n";
}
void setLevel(int) override { }
};
| Principle | Summary | C++ Example |
|---|---|---|
| Single Responsibility | One class, one reason to change | Separate User from UserSerializer |
| Open/Closed | Open for extension, closed for modification | Virtual functions, inheritance |
| Liskov Substitution | Subtypes must be substitutable | Square shouldn't inherit Rectangle |
| Interface Segregation | Prefer small, specific interfaces | Split IWorker into IWorkable, IFeedable |
| Dependency Inversion | Depend on abstractions | Inject IDatabase& not MySQLDatabase |
class ShapeFactory {
public:
static std::unique_ptr<Shape> create(std::string_view type, double param) {
if (type == "circle") {
return std::make_unique<Circle>(param);
}
if (type == "square") {
return std::make_unique<Square>(param);
}
throw std::invalid_argument("Unknown shape type");
}
};
// Usage
auto shape = ShapeFactory::create("circle", 5.0);
class Logger {
private:
Logger() = default;
public:
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
static Logger& instance() {
static Logger instance; // Thread-safe in C++11
return instance;
}
void log(std::string_view msg) { std::cout << msg << "\n"; }
};
class IObserver {
public:
virtual ~IObserver() = default;
virtual void onNotify(const std::string& event) = 0;
};
class Subject {
std::vector<IObserver*> observers_;
public:
void attach(IObserver* obs) { observers_.push_back(obs); }
void detach(IObserver* obs) {
observers_.erase(std::remove(observers_.begin(), observers_.end(), obs),
observers_.end());
}
void notify(const std::string& event) {
for (auto* obs : observers_) {
obs->onNotify(event);
}
}
};
class ICompressionStrategy {
public:
virtual ~ICompressionStrategy() = default;
virtual std::vector<uint8_t> compress(std::span<const uint8_t> data) = 0;
};
class ZipStrategy : public ICompressionStrategy {
public:
std::vector<uint8_t> compress(std::span<const uint8_t> data) override {
// ZIP compression
return {};
}
};
class Compressor {
std::unique_ptr<ICompressionStrategy> strategy_;
public:
void setStrategy(std::unique_ptr<ICompressionStrategy> s) {
strategy_ = std::move(s);
}
std::vector<uint8_t> compress(std::span<const uint8_t> data) {
return strategy_->compress(data);
}
};
| Issue | Cause | Solution |
|---|---|---|
| Object slicing | Passing by value | Use references/pointers |
| Memory leak | Missing virtual destructor | Add virtual ~Base() = default; |
| Diamond problem | Multiple inheritance | Use virtual inheritance |
| Tight coupling | Direct dependencies | Inject interfaces |
#include <gtest/gtest.h>
TEST(ShapeTest, CircleArea) {
Circle c(5.0);
EXPECT_NEAR(c.area(), 78.5398, 0.0001);
}
TEST(ShapeTest, Polymorphism) {
std::unique_ptr<Shape> shape = std::make_unique<Circle>(1.0);
EXPECT_EQ(shape->name(), "Circle");
}
TEST(FactoryTest, CreateCircle) {
auto shape = ShapeFactory::create("circle", 5.0);
EXPECT_NE(shape, nullptr);
EXPECT_EQ(shape->name(), "Circle");
}
C++ Plugin v3.0.0 - Production-Grade Learning Skill
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.