
在 C++ 编程中,容器(如vector、list、map等)和继承是两个强大的语言特性。当它们结合使用时,可以构建出高度灵活且可扩展的系统。然而,这种组合也带来了许多复杂性和潜在的陷阱。
C++ 标准库提供了多种容器,主要分为以下几类:
vector、deque、list、forward_listset、multiset、map、multimapunordered_set、unordered_multiset、unordered_map、unordered_multimapstack、queue、priority_queue所有容器都支持一些基本操作,如:
push_back()、insert()等erase()、pop_back()等[]、at()、front()、back()等begin()、end()等不同容器有不同的内存管理策略:
vector:连续内存,动态扩展list:双向链表,非连续内存map:红黑树,动态平衡继承是面向对象编程的核心概念之一,它允许一个类(派生类)继承另一个类(基类)的属性和方法。
class Shape {
public:
virtual double area() const = 0;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double area() const override { return 3.14 * radius * radius; }
};通过虚函数和动态绑定,基类指针可以根据实际对象类型调用相应的函数。
void printArea(const Shape& shape) {
std::cout << "Area: " << shape.area() << std::endl;
}
Circle circle(5.0);
printArea(circle); // 动态调用 Circle::area()包含纯虚函数的类称为抽象类,不能实例化,只能作为基类。
class Shape {
public:
virtual double area() const = 0; // 纯虚函数
};考虑一个图形库,需要存储多种不同类型的图形:
#include <vector>
#include <memory>
class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() {}
};
class Circle : public Shape {
// ...
};
class Rectangle : public Shape {
// ...
};
// 存储基类指针的容器
std::vector<Shape*> shapes;
shapes.push_back(new Circle(5.0));
shapes.push_back(new Rectangle(3.0, 4.0));为避免内存泄漏,推荐使用智能指针:
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) {
std::cout << "Area: " << shape->area() << std::endl;
}当将派生类对象直接赋值给基类对象时,派生类的特有部分会被 “切掉”,只保留基类部分。
Circle circle(5.0);
Shape shape = circle; // 对象切片,只复制基类部分对象切片会导致多态失效:
void printArea(Shape shape) { // 按值传递,发生切片
std::cout << "Area: " << shape.area() << std::endl;
}
Circle circle(5.0);
printArea(circle); // 调用的是 Shape::area(),而非 Circle::area()void printArea(const Shape& shape) { // 按引用传递,避免切片
std::cout << "Area: " << shape.area() << std::endl;
}std::vector<std::shared_ptr<Shape>> shapes;
shapes.push_back(std::make_shared<Circle>(5.0));虚函数通过虚函数表实现,会有一定的性能开销:
存储指针的容器可能导致内存碎片化,影响缓存命中率:
// 内存碎片化示例
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));
// 每个对象可能位于不同的内存位置reserve())减少重新分配次数#include <iostream>
#include <vector>
#include <memory>
#include <string>
// 手动实现 make_unique
#if __cplusplus < 201402L
namespace std {
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}
#endif
class Shape {
public:
virtual double area() const = 0;
virtual std::string name() const = 0;
virtual ~Shape() {}
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double area() const override { return 3.14 * radius * radius; }
std::string name() const override { return "Circle"; }
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() const override { return width * height; }
std::string name() const override { return "Rectangle"; }
};
int main() {
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) {
std::cout << shape->name() << " area: " << shape->area() << std::endl;
}
return 0;
}
#include <iostream>
#include <vector>
#include <memory>
class Character {
public:
virtual void attack() = 0;
virtual void defend() = 0;
virtual ~Character() {}
};
class Warrior : public Character {
public:
void attack() override { std::cout << "Warrior attacks with sword!" << std::endl; }
void defend() override { std::cout << "Warrior defends with shield!" << std::endl; }
};
class Mage : public Character {
public:
void attack() override { std::cout << "Mage casts fireball!" << std::endl; }
void defend() override { std::cout << "Mage uses magic barrier!" << std::endl; }
};
int main() {
std::vector<std::shared_ptr<Character>> party;
party.push_back(std::make_shared<Warrior>());
party.push_back(std::make_shared<Mage>());
for (const auto& character : party) {
character->attack();
character->defend();
}
return 0;
}
#include <iostream>
#include <vector>
#include <memory>
// 手动实现 make_unique
#if __cplusplus < 201402L
namespace std {
template<typename T, typename... Args>
unique_ptr<T> make_unique(Args&&... args) {
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}
#endif
class Event {
public:
virtual void process() = 0;
virtual ~Event() {}
};
class MouseEvent : public Event {
private:
int x, y;
public:
MouseEvent(int x, int y) : x(x), y(y) {}
void process() override {
std::cout << "Processing mouse event at (" << x << ", " << y << ")" << std::endl;
}
};
class KeyEvent : public Event {
private:
char key;
public:
KeyEvent(char k) : key(k) {}
void process() override {
std::cout << "Processing key event: " << key << std::endl;
}
};
class EventManager {
private:
std::vector<std::unique_ptr<Event>> events;
public:
void addEvent(std::unique_ptr<Event> event) {
events.push_back(std::move(event));
}
void processAllEvents() {
for (auto& event : events) {
event->process();
}
events.clear();
}
};
int main() {
EventManager manager;
manager.addEvent(std::make_unique<MouseEvent>(100, 200));
manager.addEvent(std::make_unique<KeyEvent>('A'));
manager.processAllEvents();
return 0;
}
std::unique_ptr、std::shared_ptr)std::mutex)或原子操作vectorlistmap或unordered_map容器与继承是 C++ 中两个强大的语言特性,它们的结合可以构建出高度灵活且可扩展的系统。但在使用过程中,需要注意以下几点:
通过合理运用容器与继承的组合,可以设计出更加优雅、高效的 C++ 程序。