C++笔记之基类指针动态地指向某一个子类情况列举

news2024/12/22 23:28:44

C++笔记之基类指针动态地指向某一个子类情况列举

code review!

文章目录

  • C++笔记之基类指针动态地指向某一个子类情况列举
    • 1.基本的多态示例
    • 2.基类中的成员函数可以设置为纯虚函数
    • 3.将基本示例修改为使用智能指针并在堆上实例化子类
    • 4.父类指针指向基类后,可以去调用只有子类才有的成员函数吗?
    • 5.子类和基类的构造函数之间的关系
    • 6.若子类和基类的构造函数不同情况一(没有用虚函数)
    • 7.若子类和基类的构造函数不同情况二(没有用虚函数)
    • 8.若子类和基类的构造函数不同情况三(修改情况二的代码为堆上实例化,使用虚函数)
    • 9.C++中的构造函数(constructor)不能被声明为虚函数。
    • 10.C++中基类指针动态地指向某一个子类(结合switch使用)情况一
    • 11.C++中基类指针动态地指向某一个子类(结合switch使用)情况二,使用智能指针
    • 12.C++中基类指针动态地指向某一个子类(结合switch使用)情况三,在switch前就在堆上实例化
    • 13.C++中基类指针动态地指向某一个子类(结合switch使用)情况三,在switch前就在堆上实例化,使用智能指针和std::move

1.基本的多态示例

在这里插入图片描述

代码

#include <iostream>

class Base {
public:
    virtual void display() {
        std::cout << "This is the Base class." << std::endl;
    }
};

class Derived1 : public Base {
public:
    void display() override {
        std::cout << "This is Derived1." << std::endl;
    }
};

class Derived2 : public Base {
public:
    void display() override {
        std::cout << "This is Derived2." << std::endl;
    }
};

int main() {
    Base* ptr;

    Derived1 derived1;
    Derived2 derived2;

    ptr = &derived1;
    ptr->display(); // 输出:This is Derived1.

    ptr = &derived2;
    ptr->display(); // 输出:This is Derived2.

    return 0;
}

2.基类中的成员函数可以设置为纯虚函数

在这里插入图片描述

3.将基本示例修改为使用智能指针并在堆上实例化子类

在这里插入图片描述

代码

#include <iostream>
#include <memory>

class Base {
public:
    virtual void display() {
        std::cout << "This is the Base class." << std::endl;
    }
    virtual ~Base() {} // Virtual destructor to ensure proper cleanup
};

class Derived1 : public Base {
public:
    void display() override {
        std::cout << "This is Derived1." << std::endl;
    }
};

class Derived2 : public Base {
public:
    void display() override {
        std::cout << "This is Derived2." << std::endl;
    }
};

int main() {
    std::unique_ptr<Base> ptr;

    ptr = std::make_unique<Derived1>();
    ptr->display(); // 输出:This is Derived1.

    ptr = std::make_unique<Derived2>();
    ptr->display(); // 输出:This is Derived2.

    return 0;
}

4.父类指针指向基类后,可以去调用只有子类才有的成员函数吗?

在这里插入图片描述

5.子类和基类的构造函数之间的关系

在这里插入图片描述

6.若子类和基类的构造函数不同情况一(没有用虚函数)

在这里插入图片描述

代码

#include <iostream>

class Base {
private:
    int baseValue;

public:
    Base(int value) : baseValue(value) {
        std::cout << "Base constructor with value: " << baseValue << std::endl;
    }

    void display() {
        std::cout << "Base value: " << baseValue << std::endl;
    }
};

class Derived : public Base {
private:
    int derivedValue;

public:
    // 子类构造函数调用基类构造函数,然后初始化子类成员
    Derived(int baseVal, int derivedVal) : Base(baseVal), derivedValue(derivedVal) {
        std::cout << "Derived constructor with values: " << baseVal << ", " << derivedVal << std::endl;
    }

    void display() {
        Base::display(); // 调用基类的 display 函数
        std::cout << "Derived value: " << derivedValue << std::endl;
    }
};

int main() {
    Derived derived(10, 20);

    derived.display();

    return 0;
}

7.若子类和基类的构造函数不同情况二(没有用虚函数)

在这里插入图片描述

代码

#include <iostream>

class Base {
private:
    int baseValue;

public:
    Base() : baseValue(0) {
        std::cout << "Base default constructor" << std::endl;
    }

    void display() {
        std::cout << "Base value: " << baseValue << std::endl;
    }
};

class Derived : public Base {
private:
    int derivedValue;

public:
    // 子类构造函数有参数,调用基类默认构造函数,然后初始化子类成员
    Derived(int derivedVal) : Base(), derivedValue(derivedVal) {
        std::cout << "Derived constructor with value: " << derivedVal << std::endl;
    }

    void display() {
        Base::display(); // 调用基类的 display 函数
        std::cout << "Derived value: " << derivedValue << std::endl;
    }
};

int main() {
    Derived derived(20);

    derived.display();

    return 0;
}

8.若子类和基类的构造函数不同情况三(修改情况二的代码为堆上实例化,使用虚函数)

在这里插入图片描述

运行
在这里插入图片描述

代码

#include <iostream>

class Base {
private:
    int baseValue;

public:
    Base() : baseValue(0) {
        std::cout << "Base default constructor" << std::endl;
    }

    virtual ~Base() {
        std::cout << "Base destructor" << std::endl;
    }

    virtual void display() {
        std::cout << "Base value: " << baseValue << std::endl;
    }
};

class Derived : public Base {
private:
    int derivedValue;

public:
    // 子类构造函数有参数,调用基类默认构造函数,然后初始化子类成员
    Derived(int derivedVal) : Base(), derivedValue(derivedVal) {
        std::cout << "Derived constructor with value: " << derivedVal << std::endl;
    }

    ~Derived() {
        std::cout << "Derived destructor" << std::endl;
    }

    void display() {
        Base::display(); // 调用基类的 display 函数
        std::cout << "Derived value: " << derivedValue << std::endl;
    }
};

int main() {
    Base* ptr = new Derived(20);

    ptr->display();

    delete ptr;

    return 0;
}

9.C++中的构造函数(constructor)不能被声明为虚函数。

10.C++中基类指针动态地指向某一个子类(结合switch使用)情况一

在这里插入图片描述

运行
在这里插入图片描述

代码

#include <iostream>

class Base {
public:
    virtual void display() {
        std::cout << "This is the Base class." << std::endl;
    }
};

class Derived1 : public Base {
public:
    void display() override {
        std::cout << "This is Derived1." << std::endl;
    }
};

class Derived2 : public Base {
public:
    void display() override {
        std::cout << "This is Derived2." << std::endl;
    }
};

int main() {
    int choice;
    Base* ptr = nullptr;

    std::cout << "Enter your choice (1 for Derived1, 2 for Derived2): ";
    std::cin >> choice;

    switch (choice) {
        case 1:
            ptr = new Derived1;
            break;
        case 2:
            ptr = new Derived2;
            break;
        default:
            std::cout << "Invalid choice." << std::endl;
            return 1;
    }

    if (ptr) {
        ptr->display();
        delete ptr;
    }

    return 0;
}

11.C++中基类指针动态地指向某一个子类(结合switch使用)情况二,使用智能指针

在这里插入图片描述

运行
在这里插入图片描述

代码

#include <iostream>
#include <memory> // 包含智能指针所需的头文件

class Base {
  public:
    virtual void display() {
        std::cout << "This is the Base class." << std::endl;
    }
};

class Derived1 : public Base {
  public:
    void display() override {
        std::cout << "This is Derived1." << std::endl;
    }
};

class Derived2 : public Base {
  public:
    void display() override {
        std::cout << "This is Derived2." << std::endl;
    }
};

int main() {
    int choice;

    std::cout << "Enter your choice (1 for Derived1, 2 for Derived2): ";
    std::cin >> choice;

    std::unique_ptr<Base> ptr; // 使用 std::unique_ptr 来替代原始指针

    switch (choice) {
    case 1:
        ptr = std::make_unique<Derived1>(); // 使用 std::make_unique 创建实例
        break;
    case 2:
        ptr = std::make_unique<Derived2>(); // 使用 std::make_unique 创建实例
        break;
    default:
        std::cout << "Invalid choice." << std::endl;
        return 1;
    }

    ptr->display();

    // 不再需要手动删除,unique_ptr 会在作用域结束时自动释放内存

    return 0;
}

12.C++中基类指针动态地指向某一个子类(结合switch使用)情况三,在switch前就在堆上实例化

在这里插入图片描述

代码

#include <iostream>

class Base {
public:
    virtual void display() {
        std::cout << "This is the Base class." << std::endl;
    }
};

class Derived1 : public Base {
public:
    void display() override {
        std::cout << "This is Derived1." << std::endl;
    }
};

class Derived2 : public Base {
public:
    void display() override {
        std::cout << "This is Derived2." << std::endl;
    }
};

int main() {
    Derived1* derived1 = new Derived1();
    Derived2* derived2 = new Derived2();

    int choice;

    std::cout << "Enter your choice (1 for Derived1, 2 for Derived2): ";
    std::cin >> choice;

    Base* ptr = nullptr;

    switch (choice) {
        case 1:
            ptr = derived1;
            break;
        case 2:
            ptr = derived2;
            break;
        default:
            std::cout << "Invalid choice." << std::endl;
            delete derived1;
            delete derived2;
            return 1;
    }

    ptr->display();

    delete derived1;
    delete derived2;

    return 0;
}

13.C++中基类指针动态地指向某一个子类(结合switch使用)情况三,在switch前就在堆上实例化,使用智能指针和std::move

在这里插入图片描述

运行
在这里插入图片描述

代码

#include <iostream>
#include <memory> // 包含智能指针所需的头文件

class Base {
  public:
    virtual void display() {
        std::cout << "This is the Base class." << std::endl;
    }
};

class Derived1 : public Base {
  public:
    void display() override {
        std::cout << "This is Derived1." << std::endl;
    }
};

class Derived2 : public Base {
  public:
    void display() override {
        std::cout << "This is Derived2." << std::endl;
    }
};

int main() {
    std::unique_ptr<Derived1> derived1 = std::make_unique<Derived1>();
    std::unique_ptr<Derived2> derived2 = std::make_unique<Derived2>();

    int choice;

    std::cout << "Enter your choice (1 for Derived1, 2 for Derived2): ";
    std::cin >> choice;

    std::unique_ptr<Base> ptr;

    switch (choice) {
    case 1:
        ptr = std::move(derived1); // 使用 std::move 进行所有权转移
        break;
    case 2:
        ptr = std::move(derived2); // 使用 std::move 进行所有权转移
        break;
    default:
        std::cout << "Invalid choice." << std::endl;
        return 1;
    }

    ptr->display();

    return 0; // 在作用域结束时,智能指针会自动释放内存
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/905223.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JUC系列-01】深入理解JMM内存模型的底层实现原理

一&#xff0c;深入理解JMM内存模型 1&#xff0c;什么是可见性 在谈jmm的内存模型之前&#xff0c;先了解一下并发并发编程的三大特性&#xff0c;分别是&#xff1a;可见性&#xff0c;原子性&#xff0c;有序性。可见性指的就是当一个线程修改某个变量的值之后&#xff0c…

shell脚本之sed

sed sed 即 Stream EDitor&#xff0c;和 vi 不同&#xff0c;sed是行编辑器 基本用法 sed [选项] 自身脚本用法 [支持输入标准输入管道] 常用选项&#xff1a;-n 不输出模式空间内容到屏幕&#xff0c;即不自动打印-e 多点编辑-f FILE 从指定文件中读取编辑脚本-r, -E 使用…

【TypeScript】内置对象

JavaScript 中很多内置对象&#xff0c;可以直接在 TypeScript 中当做定义好了的类型。 ECMAScript 的内置对象 Boolean、Number、String、RegExp、Date、Error、XMLHttpRequest 等 let num: Number new Number(1) let date: Date new Date() let reg: RegExp new RegExp(…

WTF Langchain极简入门: 03. 数据连接

加载文档 langchain提供多种文档加载器&#xff0c;支持多种格式、来源的文件。可以从本地存储系统加载文件&#xff0c;也可以从网上加载远端文件。想了解LangChain所支持的所有文档加载器&#xff0c;请参考Document Loaders。 在本系列课程中&#xff0c;我们将使用最基本…

Docker 搭建 LNMP + Wordpress(详细步骤)

目录 一、项目模拟 1. 项目环境 2. 服务器环境 3.任务需求 二、Linux 系统基础镜像 三、Nginx 1. 建立工作目录 2. 编写 Dockerfile 脚本 3. 准备 nginx.conf 配置文件 4. 生成镜像 5. 创建自定义网络 6. 启动镜像容器 7. 验证 nginx 四、Mysql 1.…

快速学习GO语言总结

备注&#xff1a;本博客将自己初步学习GO的总结进行分享&#xff0c;希望大家通过本博客可以在短时间内快速掌握GO的基本程序编码能力&#xff0c;如有错误请留言指正&#xff0c;谢谢&#xff01; 一、初步了解Go语言 &#xff08;一&#xff09;Go语言诞生的主要问题和目标…

shell脚本——expect脚本免交互

目录 一.Here Document 1.1.定义 1.2.多行重定向 二.expect实现免交互 2.1.基础免交互改密码 2.2.expect定义 2.3.expect基本命令 2.4.expect实现免交互ssh主机 一.Here Document 1.1.定义 使用I/O重定向的方式将命令列表提供给交互式程序&#xff0c;是标准输 入的一…

uniapp开发小程序,上传图片和视频功能

1.需求&#xff1a; 可以上传图片和视频&#xff0c;并且都可以删除&#xff0c;图片可以预览。 2.效果图 3.代码&#xff1a; <template><!-- 上传start --><view style"display: flex; flex-wrap: wrap;"><view class"update-file&quo…

FPGA解析串口指令控制spi flash完成连续写、读、擦除数据

前言 最近在收拾抽屉时找到一个某宝的spi flash模块&#xff0c;如下图所示&#xff0c;我就想用能不能串口来读写flash&#xff0c;大致过程就是&#xff0c;串口向fpga发送一条指令&#xff0c;fpga解析出指令控制flah&#xff0c;这个指令协议目前就是&#xff1a; 55 AA …

达梦数据库表空间创建和管理

概述 本文将介绍在达梦数据库如何创建和管理表空间。 1.创建表空间 1.1表空间个数限制 理论上最多允许有65535个表空间&#xff0c;但用户允许创建的表空间 ID 取值范围为0~32767&#xff0c; 超过 32767 的只允许系统使用&#xff0c;ID 由系统自动分配&#xff0c;ID不能…

周易卦爻解读笔记——小过

第六十二卦小过 雷山小过 震上艮下 小过卦为母卦&#xff0c;象征小有过越。 小过卦是中孚卦的错卦&#xff0c;序卦传【有信者必行之&#xff0c;故受之以小过】 小过&#xff1a;亨&#xff0c;利贞&#xff0c;可小事&#xff0c;不可大事。飞鸟遗之音&#xff0c;不宜上宜…

NEO-6M GPS模块 +无线透传模块组成短距离数据空中传输

NEO-6M GPS模块 无线透传模块组成短距离数据空中传输 &#x1f4cc;相关篇《GY-NEO6MV2 GPS模块测试》 &#x1f33f;NEO-6M GPS模块 &#x1f33f;透传模块采用的是GC2400-TC017 ✨数据的一收一发&#xff0c;需要配合一个USB转TTL工具&#xff0c;在电脑端通过串口调试助…

7-5 螺旋方阵

分数 20 全屏浏览题目 切换布局 作者 C课程组 单位 浙江大学 所谓“螺旋方阵”&#xff0c;是指对任意给定的N&#xff0c;将1到NN的数字从左上角第1个格子开始&#xff0c;按顺时针螺旋方向顺序填入NN的方阵里。本题要求构造这样的螺旋方阵。 输入格式&#xff1a; 输入在…

第3步---MySQL的DDL和DML操作

第3步---MySQL的DDL和DML操作 1.DDL操作 Data Defination Language 数据定义语言。创建数据库和表的不涉及到数据的操作。 1.1DDL基本操作 1.1.1数据库相关操作 ddl&#xff1a;创建数据库&#xff0c;创建和修改表 对数据库常见的操作&#xff1a; 操作数据库 -- 展示数据…

Unity 之 Input类

文章目录 总述具体介绍 总述 Input 类是 Unity 中用于处理用户输入的重要工具&#xff0c;它允许您获取来自键盘、鼠标、触摸屏和控制器等设备的输入数据。通过 Input 类&#xff0c;您可以轻松地检测按键、鼠标点击、鼠标移动、触摸、控制器按钮等用户输入事件。以下是关于 I…

拥塞控制(TCP限制窗口大小的机制)

拥塞控制机制可以使滑动窗口在保证可靠性的前提下&#xff0c;提高传输效率 关于滑动窗口的属性以及部分机制推荐看TCP中窗口和滑动窗口的含义以及流量控制 拥塞控制出现的原因 看了上面推荐的博客我们已经知道了&#xff0c;由于接收方接收数据的能力有限&#xff0c;所以要通…

js IntersectionObserver简单案例

效果 源码 <!DOCTYPE html> <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content&q…

IP库新增经过实践的Verilog 库

网上严重缺乏实用的 Verilog 设计。Project F 库是尝试让 FPGA 初学者变得更好部分。 设计包括 Clock- 时钟生成 (PLL) 和域交叉Display - 显示时序、帧缓冲区、DVI/HDMI 输出Essential- 适用于多种设计的便捷模块Graphics- 绘制线条和形状Maths- 除法、LFSR、平方根、正弦....…

Vue--》打造个性化医疗服务的医院预约系统(七)完结篇

今天开始使用 vue3 + ts 搭建一个医院预约系统的前台页面,因为文章会将项目的每一个地方代码的书写都会讲解到,所以本项目会分成好几篇文章进行讲解,我会在最后一篇文章中会将项目代码开源到我的GithHub上,大家可以自行去进行下载运行,希望本文章对有帮助的朋友们能多多关…

Android OpenCV(七十四): Android OpenCV SDK 升级至 4.8.0

前言 如昨日文章所述,OpenCV 4.8.0 已经发布,虽然系列文章已经停更很久,但是版本升级工作笔者是很乐意快速完成的。 OpenCV 4.8.0 Android SDK:https://github.com/opencv/opencv/releases/download/4.8.0/opencv-4.8.0-android-sdk.zip 更新日志:https://github.com/o…