C++中std::shared_ptr数组的工作原理及多态打印实现问题
实现基类智能指针指向派生类时的多态打印
嘿,作为C初学者,你选的这个练习点特别棒——多态+智能指针,这俩都是C里非常核心的知识点。咱们一步步来解决你的需求:让基类智能指针指向不同派生类对象时,能自动打印对应类的专属信息。
首先,先说说你现有代码里的小问题:你给基类定义的纯虚函数叫triangle(),这个名字只适合Triangle类,对等腰、等边三角形来说就不太合适了。咱们应该给基类定义一个通用的纯虚函数,比如printInfo(),让所有派生类都重写这个函数来输出自己的专属信息。
接下来是完整的可运行代码,我给你补全并标注了关键细节:
#include <iostream> #include <memory> // 抽象基类 Shape class Shape { public: // 通用纯虚函数:让所有派生类实现自己的信息打印逻辑 virtual void printInfo() const = 0; // 必须声明虚析构函数!否则智能指针销毁对象时不会调用派生类析构 virtual ~Shape() { std::cout << "Shape 被销毁...\n"; } }; // 普通三角形类,继承自 Shape class Triangle : public Shape { public: // 用 override 关键字明确重写基类虚函数,编译器会帮你检查正确性 void printInfo() const override { std::cout << "我是普通三角形类,三条边长度各不相同\n"; } ~Triangle() override { std::cout << "Triangle 被销毁...\n"; } }; // 等腰三角形类,继承自 Triangle class Isosceles : public Triangle { public: void printInfo() const override { std::cout << "我是等腰三角形类,有两条边长度相等\n"; } ~Isosceles() override { std::cout << "Isosceles 被销毁...\n"; } }; // 等边三角形类,继承自 Isosceles class Equilateral : public Isosceles { public: void printInfo() const override { std::cout << "我是等边三角形类,三条边长度完全相等\n"; } ~Equilateral() override { std::cout << "Equilateral 被销毁...\n"; } }; int main() { // 使用 std::unique_ptr 智能指针管理对象,无需手动释放内存 std::unique_ptr<Shape> shape1 = std::make_unique<Triangle>(); std::unique_ptr<Shape> shape2 = std::make_unique<Isosceles>(); std::unique_ptr<Shape> shape3 = std::make_unique<Equilateral>(); // 调用虚函数,自动匹配对应派生类的实现 shape1->printInfo(); shape2->printInfo(); shape3->printInfo(); // 智能指针会在main函数结束时自动销毁对象,不用写delete return 0; }
关键知识点拆解
- 多态的核心:虚函数重写:基类的纯虚函数
printInfo()是多态的入口,派生类用override重写后,当基类智能指针指向派生类对象时,会自动调用对应派生类的printInfo()实现,这就是多态的魔力。 - 虚析构函数的必要性:如果基类析构函数不是虚函数,智能指针销毁对象时只会调用基类的析构函数,派生类的资源无法正确释放,会导致内存泄漏或未定义行为。
- 智能指针的正确用法:
std::make_unique是创建unique_ptr的推荐方式,它比手动new更安全,能避免内存泄漏,而且unique_ptr会在作用域结束时自动释放对象,彻底告别手动管理内存的麻烦。
运行结果
运行这段代码后,你会看到:
我是普通三角形类,三条边长度各不相同 我是等腰三角形类,有两条边长度相等 我是等边三角形类,三条边长度完全相等 Equilateral 被销毁... Isosceles 被销毁... Triangle 被销毁... Shape 被销毁... Isosceles 被销毁... Triangle 被销毁... Shape 被销毁... Triangle 被销毁... Shape 被销毁...
销毁顺序是从最派生类到基类,这就是虚析构函数起的作用,确保每个类的析构逻辑都能被执行。
内容的提问来源于stack exchange,提问作者Const
相关产品推荐
相关产品推荐

