自学内容网 自学内容网

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

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)来自动管理内存,减少内存泄漏的风险。

原文地址:https://blog.csdn.net/m0_72883750/article/details/144705491

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!