本题考察 C++ 智能指针在多态场景下的行为,需要逐一分析每个选项的正确性。
std::unique_ptr<Base> 可以持有 Derived 对象,但要求基类 Base 有虚析构函数,否则通过基类指针删除派生类对象会导致未定义行为(只调用基类析构,派生类资源未释放)。因此 A 正确。
std::shared_ptr<Base> 即使基类没有虚析构函数,也能正确析构 Derived 对象。这是因为 shared_ptr 在构造时会通过控制块(control block)存储实际的删除器(默认删除器会使用派生类的析构),与基类是否虚无关。例如:
struct Base { ~Base() { cout << "~Base"; } }; struct Derived : Base { ~Derived() { cout << "~Derived"; } }; shared_ptr<Base> p = make_shared<Derived>(); // 输出 ~Derived~Base
因此 B 正确。
std::make_shared<Derived>() 返回 shared_ptr<Derived>,可以隐式转换为 shared_ptr<Base>(因为 Derived* 可转换为 Base*,且 shared_ptr 支持向上转型)。因此 C 正确。
std::unique_ptr<Base[]> 用于管理动态数组。若存储 Derived 对象数组,通过基类指针调用 delete[] 是未定义行为(即使基类有虚析构函数,数组删除也需要动态类型与指针类型严格一致)。因此 D 错误。
A、B、C 正确。