C/C++ | 每日一练 (2)

💢欢迎来到张胤尘的技术站
💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥

文章目录

  • C/C++ | 每日一练 (2)
    • 题目
    • 参考答案
      • 封装
      • 继承
      • 多态
        • 虚函数
        • 底层实现
          • 单继承
          • 多继承
        • 注意事项

C/C++ | 每日一练 (2)

题目

简述 c++ 面向对象的三大特性。

参考答案

面向对象三大特性:封装、继承、多态。

封装

封装指的是将对象的行为和属性结合成为一个类,并隐藏对象的内部实现细节,仅通过对象的接口(即公开的方法)与外界交互。

  • 隐藏内部实现细节:保护对象的内部状态,防止外部直接访问或修改对象的私有成员。
  • 提供统一的接口:通过公开的方法(如构造函数、成员函数等)对外提供服务,使对象的使用更加安全和方便。

例如:

#include <iostream>

class Person
{
private:
    // 私有成员,外部无法直接访问
    std::string name;
    int age;

public:
    // 提供接口访问私有成员
    void setName(const std::string &newName)
    {
        name = newName;
    }
    void setAge(int newAge)
    {
        age = newAge;
    }

    void display() const
    {
        std::cout << name << " is " << age << " years old." << std::endl;
    }
};

继承

继承是指一个类(派生类或子类)可以继承另一个类(基类或父类)的属性和方法。子类可以扩展或修改父类的功能,而无需重新编写相同的代码,支持代码重用和扩展。继承可以是单继承或多继承(在 c++ 中支持)

继承的主要作用是:

  • 代码复用:减少重复代码,提高开发效率。
  • 拓展功能:派生类可以在继承基类的基础上,添加新的功能或修改现有功能。
#include <iostream>

class Animal
{
public:
    void eat()
    {
        std::cout << "animal eat" << std::endl;
    }
};

class Dog : public Animal
{
public:
    void bark()
    {
        std::cout << "dog eat" << std::endl;
    }
};

多态

多态是指相同的接口在不同的类实例上具有不同的表现形式。多态分为:

  • 编译时多态(函数重载和运算符重载)

  • 运行时多态(通过虚函数实现)。

运行时多态是面向对象编程中最重要的多态形式,它通过虚函数和继承实现。

例如:

#include <iostream>

class Shape
{
public:
    // 定义为虚函数
    virtual void draw() const
    {
        std::cout << "drawing a shape" << std::endl;
    }
};

class Circle : public Shape
{
public:
    // 重写基类的虚函数
    void draw() const override
    {
        std::cout << "drawing a circle" << std::endl;
    }
};

class Square : public Shape
{
public:
    // 重写基类的虚函数
    void draw() const override
    {
        std::cout << "drawing a square" << std::endl;
    }
};

int main()
{
    Shape *s1 = new Circle();
    Shape *s2 = new Square();

    s1->draw(); // drawing a circle
    s2->draw(); // drawing a square
    
    delete s1;
    delete s2;
}
虚函数

c++ 中,虚函数是实现运行时多态的关键机制。它允许派生类重写继承自基类的成员函数,从而在运行时根据对象的实际类型调用相应的函数实现。

虚函数是在基类中通过关键字 virtual 声明的成员函数。它的作用是让派生类可以覆盖该函数,从而实现多态行为。

#include <iostream>

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

虚函数的主要作用是实现 动态绑定或运行时多态。具体来说:

  • 当通过基类指针或引用调用虚函数时,程序会根据对象的实际类型(派生类类型)来调用对应的函数实现。
  • 如果没有虚函数,调用的将是基类的成员函数,而不是派生类的实现,这种行为称为静态绑定
#include <iostream>

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

class Derived : public Base {
public:
    // 重写基类的虚函数
    void display() override {
        std::cout << "Derived::display()" << std::endl;
    }
};

int main() {
    Base* ptr = new Derived();
    delete ptr;
    return 0;
}

在上述代码中,ptr 是基类指针指向子类对象,由于 display() 是虚函数,程序会调用派生类的 display() 的实现。

底层实现

虚函数的实现依赖于虚表(简称 vtable)和虚表指针vptr):

  • 每个包含虚函数的类都有一个虚表(vtable),虚表中存储了该类中所有虚函数的地址。
  • 每个对象在对象头中会隐式地包含一个虚表指针(vptr),指向其所属类的虚表。
  • 当通过基类指针或引用调用虚函数时,程序会通过 vptr 查找虚表,然后在虚表中根据函数索引找到正确的函数地址。
  • 执行函数调用。
单继承

单继承的动态多态结构图如下所示:

在这里插入图片描述

多继承

多继承是 c++ 中的一种继承方式,它允许一个子类从多个基类继承属性和行为。这种继承方式可以提供更大的灵活性,使得派生类能够组合多个基类的特性。但是,多继承也引入了复杂性,尤其是在内存布局、虚函数表、构造和析构顺序等方面。多继承的动态多态结构图如下所示:

#include <iostream>

class Base1
{
public:
	virtual void display()
	{
		std::cout << "Base1::display()" << std::endl;
	}

	virtual void show()
	{
		std::cout << "Base1::show()" << std::endl;
	}

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

private:
	int a;
	int b;
};

class Base2
{
public:
	virtual void cat()
	{
		std::cout << "Base2::cat()" << std::endl;
	}
	virtual ~Base2()
	{
		std::cout << "Base2::~Base2()" << std::endl;
	}

private:
	int c;
};

class Derived : public Base1, public Base2
{
public:
	// 重写基类的虚函数
	void display() override
	{
		std::cout << "Derived::display()" << std::endl;
	}
	void cat() override
	{
		std::cout << "Derived::cat()" << std::endl;
	}
	~Derived() override 
	{
		std::cout << "Derived::~Derived" << std::endl;
	}
private:
	int d;
};

int main() {
	Base1* ptr1 = new Derived();
	Base2* ptr2 = new Derived();
	delete ptr1;
	delete ptr2;
	return 0;
}

在这里插入图片描述

注意事项
  • 虚函数必须是成员函数:全局函数或静态成员函数不能声明为虚函数。
  • 派生类的覆盖函数必须与基类的虚函数具有相同的签名(函数名、参数类型和数量)。如果派生类的函数与基类虚函数签名不一致(函数名相同,参数类型和数量不相同),则不会覆盖而是隐藏。
  • 纯虚函数:在基类中,可以将虚函数声明为纯虚函数,即在声明时赋值为 = 0。包含纯虚函数的类称为抽象类,不能实例化对象。
class AbstractClass {
public:
    virtual void func() = 0;  // 纯虚函数
};
  • 析构函数的虚化:如果基类有虚函数,通常需要将析构函数声明为虚函数,以确保通过基类指针删除派生类对象时,能够正确调用派生类的析构函数。
class Base {
public:
    virtual ~Base() { cout << "Base destructor" << endl; }
};

class Derived : public Base {
public:
    ~Derived() { cout << "Derived destructor" << endl; }
};
  • 虚函数的实现依赖于虚表和虚表指针,因此会带来一定的性能开销;每个对象需要存储一个虚表指针(通常为 4 字节或 8 字节)。
  • 动态多态在调用虚函数时需要通过虚表查找函数地址,这比直接调用非虚函数稍慢。但是这种开销通常是可以接受的,特别是在需要多态的场景中。

🌺🌺🌺撒花!

如果本文对你有帮助,就点关注或者留个👍
如果您有任何技术问题或者需要更多其他的内容,请随时向我提问。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

13th Labour of Heracles CodeForces - 1466D

题目&#xff1a;题目链接 题目大意 题目描述 给定一棵树&#xff0c;它的每个点都有对应的权值。 定义颜色x的同色子图为图中所有颜色为x的边&#xff0c;及其顶点形成的同色子图。 一个同色连通块的权值为该连通块所包含的点的权值的和。 一个同色子图的权值定义为子图内…

在多项目并行时,若遇到项目冲突的情况应该如何处理

在项目管理中&#xff0c;尤其是在多项目并行的情况下&#xff0c;项目冲突是一个不可避免的问题。当多个项目同时进行时&#xff0c;由于资源有限、时间紧张或优先级不清晰&#xff0c;常常会发生资源冲突、进度冲突、需求冲突等问题。解决项目冲突的关键在于有效的沟通、优先…

Linux 驱动入门(5)—— DHT11(温湿度传感器)驱动

文章目录 一、编译替换内核和设备树二、DHT11 温湿度传感器1. DHT11 简介2. 数据格式3. 编程思路 三、驱动代码1. GPIO 实现1.1 驱动层代码1.2 应用层代码 2. 设备树实现2.1 修改设备树2.2 驱动层代码2.3 应用层代码 3. 上机测试 一、编译替换内核和设备树 在编译驱动程序之前…

Docker仿真宇树狗GO1

1. 启动容器 docker run -it --rm humble_suo bash2. 安装Go1 的仿真包 apt update apt install -y git cmake build-essential git clone https://github.com/unitreerobotics/unitree_ros.git cd unitree_ros colcon build source install/setup.bash3. 启动仿真环境 ros2…

网页制作06-html,css,javascript初认识のhtml如何建立超链接

超链接有外部链接、电子邮件链接、锚点链接、空链接、脚本链接 一、内部链接 与自身网站页面有关的链接被称为内部链接 1、创建内部链接 1&#xff09;语法&#xff1a; <a href"链接地址"> …… </a> 2&#xff09;举例应用&#xff1a; 3&#xf…

brew Nushell mac升级版本

运行命令&#xff1a; brew upgrade nushell 国内更新比较慢建议架个梯子。 如果没有更新则先更新一下brew brew update 更新后看下版本是否死最新的了

使用IDEA提交SpringBoot项目到Gitee上

登录Gitee并新建仓库 创建本地仓库 提交本地代码到本地仓库 提交本地代码到远程仓库

selenium爬取苏宁易购平台某产品的评论

目录 selenium的介绍 1、 selenium是什么&#xff1f; 2、selenium的工作原理 3、如何使用selenium&#xff1f; webdriver浏览器驱动设置 关键步骤 代码 运行结果 注意事项 selenium的介绍 1、 selenium是什么&#xff1f; 用于Web应用程序测试的工具。可以驱动浏览…

2025前端框架最新组件解析与实战技巧:Vue与React的革新之路

作者&#xff1a;飞天大河豚 引言 2025年的前端开发领域&#xff0c;Vue与React依然是开发者最青睐的框架。随着Vue 3的全面普及和React 18的持续优化&#xff0c;两大框架在组件化开发、性能优化、工程化支持等方面均有显著突破。本文将从最新组件特性、使用场景和编码技巧三…

基于AVue的二次封装:快速构建后台管理系统的CRUD方案

基于AVue的二次封装&#xff1a;快速构建后台管理系统的CRUD方案 在开发后台管理系统时&#xff0c;表格是常见的组件之一。然而&#xff0c;使用原生的Element Plus实现CRUD&#xff08;增删改查&#xff09;功能往往需要编写大量重复代码&#xff0c;过程繁琐。即使借助类似…

实验 Figma MCP + Cursor 联合工作流

开源项目 Figma-Context-MCP 介绍 使用此 Model Context Protocol 服务器授予 Cursor 对 Figma 文件的访问权限。 当 Cursor 可以访问 Figma 设计数据时&#xff0c;它比粘贴屏幕截图等其他方法更能准确地进行代码转化。 开源仓库&#xff1a; GLips/Figma-Context-MCP 具体…

C语言(11)------------->while循环

一、if与while的区别 在C语言中&#xff0c;有三大结构&#xff0c;分别是顺序、选择和循环。在前面的博客文章中&#xff0c;我们解释了if语句的用法&#xff0c;可以参考&#xff1a;C语言&#xff08;7&#xff09;------------&#xff1e;if语句-CSDN博客 从文章中&…

将 Vue 项目打包后部署到 Spring Boot 项目中的全面指南

将 Vue 项目打包后部署到 Spring Boot 项目中的全面指南 在现代 Web 开发中&#xff0c;前后端分离架构已经成为主流。然而&#xff0c;在某些场景下&#xff0c;我们可能需要将前端项目&#xff08;如 Vue&#xff09;与后端项目&#xff08;如 Spring Boot&#xff09;集成部…

Linux--进程(进程虚拟地址空间、页表、进程控制、实现简易shell)

一、进程虚拟地址空间 这里以kernel 2.6.32&#xff0c;32位平台为例。 1.空间布局 在 32 位系统中&#xff0c;虚拟地址空间大小为 4GB。其中&#xff1a; 内核空间&#xff1a;占据高地址的 1GB &#xff0c;用于操作系统内核运行&#xff0c;包含内核代码、内核数据等&am…

软件集成测试的技术要求

文章目录 一、软件集成测试的概念二、测试对象三、测试目的四、进入条件五、测试内容六、测试环境七、测试实施方一、软件集成测试的概念 软件集成测试(Software Integration Testing),也称部件测试,一种旨在暴露接口以及集成组件间交互时存在的缺陷的测试。集成测试是灰盒…

【信息系统项目管理师-案例真题】2022下半年案例分析答案和详解

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 试题一(24分)【问题1】(6分)【问题2】(10分)【问题3】(8分)试题二(26分)【问题1】(8分)【问题2】(8分)【问题3】(4分)【问题4】(6分)试题三(25分)【问题1】(12分)【问题2】(7分)【问题…

Golang GORM系列:GORM无缝集成web框架

高效的数据管理是每个成功的web应用程序的支柱。GORM是通用的Go对象关系映射库&#xff0c;它与流行的Go web框架搭配得非常好&#xff0c;提供了无缝集成&#xff0c;简化了数据交互。本指南将带你探索GORM和web框架&#xff08;如Gin&#xff0c; Echo和Beego&#xff09;之间…

C语言(22)

字符函数和字符串函数 7.strcpy/strcat/strcmp与strncpy/strncat/strncmp区别 前者是长度不受限制的字符串函数&#xff0c;后者是长度受限制的字符串函数 8.strncpy的使用 char * strncpy ( char * destination , const char * source , size_t num ) ; //拷贝num个字符从…

提升C++项目编译速度

目录 一、问题背景 二、代码规范方面的解决方案 2.1 拆分头文件 2.2 拆分巨型类 2.3 使用前置声明 2.4 避免在头文件中包含实现 2.5 避免头文件重复包含 2.6 将常用且变动较少的独立到一个文件 三、代码业务重构方面经验 3.1 使用PIMPL&#xff08;Pointer to Imple…

vue从入门到精通(十二):列表渲染

12.1 v-for指令 1.用于展示列表数据 2.语法:v-for“(item,index) in xxx” :key“yyy” 3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少) 12.2 key的原理 react、vue中的key有什么作用?(key的内部原理) 1.虚拟DOM中key的作用: key是虚拟DOM对象的标识&#…