C/C++基础知识复习(46)

news/2024/12/25 10:02:30 标签: c++, c语言, 开发语言

1) C++ 中面向对象编程如何实现动态绑定?

动态绑定(Dynamic Binding),也称为晚绑定,是指在程序运行时根据对象的实际类型来决定调用哪个方法,而不是在编译时就确定方法调用。这通常发生在继承多态的场景中,是面向对象编程中非常重要的特性。

C++ 实现动态绑定的机制依赖于 虚函数virtual)和 基类指针/引用 来引用派生类对象。动态绑定通过虚函数表(vtable)实现,虚函数表是编译器为每个含有虚函数的类生成的一个数据结构,其中包含指向虚函数的指针。

实现动态绑定的步骤:
  1. 在基类中将函数声明为 virtual
  2. 在派生类中重写该虚函数。
  3. 通过基类的指针或引用调用虚函数(即使对象实际是派生类的类型)。

C++ 编译器根据对象的实际类型来决定调用哪个函数,这个过程在运行时确定,因此称为动态绑定

示例代码:
#include <iostream> 
using namespace std; 
class Base { public: // 声明虚函数 
virtual void display() { 
cout << "Base class display" << endl; 
} 
virtual ~Base() {} // 虚析构函数,防止对象销毁时内存泄漏 
}; 
class Derived : public Base { 
public: // 重写虚函数 
void display() override { 
cout << "Derived class display" << endl; 
} }; 
int main() { 
Base* basePtr; // 基类指针 
Derived derivedObj; // 派生类对象 
basePtr = &derivedObj; // 动态绑定:运行时决定调用 Derived 的 display 方法 
basePtr->display(); 
// 输出: Derived class display 
return 0; 
}
解释:
  • Base 类中的 display 函数是虚函数,通过 virtual 关键字声明。
  • Derived 类重写了 display 函数。
  • main 函数中,basePtr 是指向基类对象的指针,但它指向一个派生类的对象。通过 basePtr 调用 display 方法时,程序会动态决定调用 Derived 类的 display 方法,而不是基类的 display 方法。

动态绑定是通过虚函数表(vtable)实现的,虚函数表在运行时根据对象的实际类型来查找和调用合适的函数。

2) C++ 如何管理内存?

C++ 的内存管理主要依赖于手动内存管理(通过 newdelete)以及栈和堆的概念。与一些自动化内存管理语言(如 Java 或 Python)不同,C++ 不会自动垃圾回收,程序员需要手动分配和释放内存。这给程序员提供了更多控制权,但也需要小心管理内存,避免内存泄漏和悬空指针等问题。

栈内存与堆内存:
  • 栈内存(Stack):用于存储局部变量和函数调用的上下文。栈内存自动管理,随着作用域的结束,栈上的对象会自动销毁。
  • 堆内存(Heap):用于存储动态分配的内存。堆内存由程序员手动管理,需要显式分配和释放。
1. 手动内存管理:newdelete

C++ 提供了 newdelete 关键字来在堆上分配和释放内存。它们的使用可以创建动态对象或数组。

  • new:分配内存并返回指向该内存的指针。
  • delete:释放通过 new 分配的内存。
  • new[]:分配数组内存。
  • delete[]:释放数组内存。
示例代码:
#include <iostream> 
using namespace std; 
int main() { 
// 在堆上分配单个整数 
int* ptr = new int(5); 
cout << "Value: " << *ptr << endl;
// 输出: Value: 5 
// 释放内存 delete ptr; 
// 在堆上分配一个整数数组 
int* arr = new int[3]; 
arr[0] = 1; 
arr[1] = 2; 
arr[2] = 3; 
// 输出数组元素 
for (int i = 0; i < 3; ++i) { 
cout << arr[i] << " "; 
// 输出: 1 2 3 
} 
cout << endl; 
// 释放数组内存 
delete[] arr; 
return 0; 
}
2. 内存泄漏和资源管理

内存泄漏是指程序分配了堆内存,但在不再需要时没有正确释放,从而导致内存无法回收。为了避免内存泄漏,程序员必须确保每次使用 new 分配的内存都必须用 deletedelete[] 释放。

RAII(资源获取即初始化)是 C++ 推荐的内存管理模式,利用类的构造函数和析构函数来确保资源的自动释放。通过智能指针(std::unique_ptrstd::shared_ptr 等)可以有效管理内存,避免手动调用 delete

3. 智能指针:自动内存管理

C++11 引入了智能指针(std::unique_ptrstd::shared_ptrstd::weak_ptr),这些指针自动管理堆内存,避免了显式调用 delete,从而减少了内存泄漏的风险。

  • std::unique_ptr:唯一拥有权的智能指针,当其生命周期结束时会自动释放内存。
  • std::shared_ptr:共享拥有权的智能指针,引用计数机制决定何时释放内存。
  • std::weak_ptr:解决循环引用问题,指向 shared_ptr 管理的对象,但不增加引用计数。
示例代码(使用 unique_ptr):
#include <iostream> 
#include <memory> 
using namespace std; 
class MyClass { public: MyClass() { 
cout << "MyClass constructed!" << endl; 
} 
~MyClass() { 
cout << "MyClass destructed!" << endl; 
} }; 
int main() { 
// 使用 unique_ptr 自动管理内存 
unique_ptr<MyClass> ptr = make_unique<MyClass>(); // 不需要显式调用 
delete,unique_ptr 会在超出作用域时自动销毁对象 
return 0; 
}

在上面的代码中,unique_ptr 自动管理 MyClass 对象的生命周期,当 ptr 超出作用域时,它所管理的对象会被自动销毁。

总结:

  • 动态绑定:通过使用 virtual 关键字在基类中声明虚函数,并通过基类指针或引用来调用派生类的重写函数,从而实现动态绑定。
  • 内存管理:C++ 提供了手动内存管理机制(newdelete),通过栈和堆内存管理不同类型的数据。此外,C++11 引入了智能指针(如 std::unique_ptrstd::shared_ptr)来自动管理内存,减少内存泄漏的风险。

http://www.niftyadmin.cn/n/5798951.html

相关文章

Flink SQL Cookbook on Zeppelin 部署使用

简介&#xff1a;对于初学者来说&#xff0c;学习 Flink 可能不是一件容易的事情。看文档是一种学习&#xff0c;更重要的是实践起来。但对于一个初学者来说要把一个 Flink SQL 跑起来还真不容易&#xff0c;要搭各种环境&#xff0c;真心累。很幸运的是&#xff0c;Flink 生态…

Android 之 List 简述

一、简单创建方式 Android 开发中&#xff0c;列表有很多种类&#xff0c;如ArrayList、LinkedList、List、MutableList等&#xff0c;创建列表的方式如下所示&#xff1a; fun listDemo() {// 使用 listOf 创建不可变的空列表val list listOf<Int>()val list1 listOf…

抖音视频下载去水印工具推荐

下载抖音视频并去水印的工具有很多&#xff0c;下面推荐几种常用且有效的方法。请注意&#xff0c;下载和去水印的视频需遵守版权和平台规定&#xff0c;避免侵犯原创者权益。 在线工具 这些工具无需安装&#xff0c;可以直接在浏览器中使用&#xff0c;操作简单&#xff1a;…

【Chrome】浏览器提示警告Chrome is moving towards a new experience

文章目录 前言一、如何去掉 前言 Chrome is moving towards a new experience that allows users to choose to browse without third-party cookies. 这是谷歌浏览器&#xff08;Chrome&#xff09;关于隐私策略更新相关的提示 提示&#xff1a;以下是本篇文章正文内容&…

步进电机位置速度双环控制实现

步进电机位置速度双环控制实现 野火stm32电机教学 提高部分-第11讲 步进电机位置速度双环控制实现(1)_哔哩哔哩_bilibili PID模型 位置环作为外环,速度环作为内环。设定目标位置和实际转轴位置的位置偏差,经过位置PID获得位置期望,然后讲位置期望(位置变化反映了转轴的速…

[机器学习]sklearn入门指南(1)

简介 scikit-learn&#xff08;简称sklearn&#xff09;是一个开源的Python机器学习库&#xff0c;它提供了简单而高效的工具用于数据挖掘和数据分析&#xff0c;并且拥有一个活跃的开发社区。它建立在NumPy、SciPy和matplotlib这些科学计算库之上&#xff0c;旨在提供一致且可…

【vue】圆环呼吸灯闪烁效果(模拟扭蛋机出口处灯光)

效果图先发&#xff1a; 页面部分&#xff1a; <div ref"round" class"round"><div class"light" ref"light"/><div class"box"></div></div>js部分(控制圆环生成&#xff09;; setRound…

解释 Python 中的装饰器及其作用?

一、装饰器的基本概念 装饰器本质上是一个函数&#xff0c;它接受一个函数作为参数&#xff0c;并返回一个新的函数。 这个新的函数通常会在原函数的基础上添加一些额外的功能&#xff0c;比如日志记录、权限验证、性能统计等。 装饰器的语法糖形式为decorator_name&#xf…