跳转至

练习:使用 dynamic_cast 安全识别派生对象


任务描述

设计多态基类 Shape、派生类 CircleRectangle,使用 dynamic_cast 判断基类指针实际指向的对象类型。

相关知识

dynamic_cast 需要多态基类(至少一个虚函数)。向下转换失败时,指针结果为 nullptr

为什么不能直接 static_cast

基类指针并不一定实际指向目标派生类。static_cast 不会在运行时检查类型,错误转换后访问对象可能产生未定义行为。dynamic_cast 会根据对象的运行时类型进行检查。

指针转换失败的处理

对指针使用 dynamic_cast 时,失败结果为 nullptr。因此 isCircle 应先判断转换结果,而不是解引用转换后的指针。

编程要求

  1. Shape 提供虚析构函数;CircleRectangle 分别覆盖 type()
  2. 完成 isCircle(const Shape* shape):仅当对象实际为 Circle 时返回 true
  3. 测试 CircleRectangle 和空指针三种情况。
  4. isCircle 的形参应为 const Shape*,函数不得修改对象。
  5. type() 的返回值用于辅助理解类型设计,不得替代 dynamic_cast 完成本题判断。

待完成代码

#include <cassert>
#include <iostream>
#include <sstream>
#include <string>

// TODO:定义 Shape、Circle、Rectangle 和 isCircle
void test() {
    Circle circle;
    Rectangle rectangle;
    assert(isCircle(&circle));
    assert(!isCircle(&rectangle));
    assert(!isCircle(nullptr));

    std::ostringstream output;
    std::streambuf* oldBuffer = std::cout.rdbuf(output.rdbuf());
    std::cout << (isCircle(&circle) ? "圆形" : "非圆形") << '\n';
    std::cout.rdbuf(oldBuffer);
    assert(output.str() == "圆形\n");
}

int main() {
    test();
    std::cout << "本关测试通过" << std::endl;
    return 0;
}

测试说明

测试依次覆盖转换成功、转换失败和空指针;仅第一种情况输出 圆形,其余两种情况应安全返回 false


开始你的任务吧,祝你成功!