1) C++ 中面向对象编程如何实现动态绑定?
动态绑定
- 成员函数必须声明为virtual
- 如果基类中声明了为虚函数,则派生类中不必再声明。
调用方式:通过对象的指针或引用调用成员函数,或通过成员函数调用,反之就无法实现动态联编。
特点:灵活,问题抽象性和问题的易维护性。
通过基类指针或引用调用虚函数时,在运行时根据实际指向的对象类型来确定调用哪个版本的函数,从而实现动态绑定。例如:
class Base {
public:
virtual void display() {
cout << "Base class display" << endl;
}
};
class Derived : public Base {
public:
void display() override {
cout << "Derived class display" << endl;
}
};
int main() {
Base* ptr = new Derived();
ptr->display(); // 调用派生类的 display 函数
delete ptr;
return 0;
}
在上述代码中,虽然ptr的类型是基类指针,但它实际指向一个派生类对象。当调用ptr->display()时,会根据实际对象的类型(派生类)在运行时确定调用派生类中的display函数,实现了动态绑定。
C++ 中的动态绑定是通过虚函数机制实现的,它允许在运行时根据对象的实际类型来确定调用哪个函数版本,从而实现多态性。
2) C++如何管理内存?
在 C++中,内存管理主要通过以下几种方式:
一、自动存储
1. 局部变量:在函数内部声明的非静态变量通常存储在栈上。当函数被调用时,为这些变量分配内存;当函数返回时,这些内存自动被释放。
void exampleFunction() {
int x = 10; // x 存储在栈上,函数返回时自动释放
}
二、动态存储
1. new和delete:使用new运算符在堆上动态分配内存,使用delete运算符释放堆上分配的内存。
int* ptr = new int(10); // 在堆上分配一个整数并初始化为 10
delete ptr; // 释放内存
2. new[]和delete[]:用于分配和释放数组类型的内存。
int* arr = new int[5];
delete[] arr;
三、静态存储
全局变量和静态变量:全局变量和在函数外部使用static关键字声明的静态变量存储在静态存储区。它们在程序开始运行时被分配内存,在程序结束时释放。
int globalVariable = 10; // 全局变量存储在静态存储区
void staticVariableExample() {
static int staticVariable = 20; // 静态局部变量也存储在静态存储区
}
四、智能指针(C++11 及以上)
1. std::unique_ptr:独占所有权的智能指针,确保一个对象只有一个所有者,在其生命周期结束时自动释放所管理的资源。
std::unique_ptr<int> ptr1(new int(10));
2. std::shared_ptr:采用引用计数的智能指针,多个shared_ptr可以共享同一个对象的所有权,当最后一个shared_ptr被销毁时,自动释放资源。
std::shared_ptr<int> ptr2(new int(20));
std::shared_ptr<int> ptr3 = ptr2; // 两个智能指针共享资源
3. std::weak_ptr:配合std::shared_ptr使用,不增加引用计数,用于解决循环引用问题。
五、内存管理的注意事项
1. 避免内存泄漏:确保动态分配的内存都被正确释放,特别是在异常情况下。
2. 防止悬空指针:在释放内存后,不要继续使用指向该内存的指针。
3. 注意内存碎片:频繁的动态内存分配和释放可能导致内存碎片,影响程序性能。可以考虑使用内存池等技术来减少内存碎片。