Talk is cheap,show the code
及时更新
类
多态
静态多态(编译时多态):
- 函数重载(Function Overloading):
实现原理:在同一作用域内,根据函数的参数列表(参数类型、参数个数或参数顺序)的不同,定义多个同名函数,编译器在编译时根据调用时的实参来决定调用哪个函数。
#include <iostream>
class Math {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
};
int main() {
Math m;
std::cout << m.add(1, 2) << std::endl;
std::cout << m.add(1.0, 2.0) << std::endl;
return 0;
}
在上述代码中,Math类中定义了两个名为add的函数,它们的参数类型不同,一个是int类型,一个是double类型。当调用add函数时,编译器会根据传入的实参类型决定调用哪个add函数。
- 运算符重载(Operator Overloading):
实现原理:通过重载运算符函数,改变运算符的默认行为,使其可以操作自定义类型。运算符重载函数可以是类的成员函数或全局函数。
#include <iostream>
class Complex {
private:
double real;
double imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {
}
Complex operator+(const Complex& c) const {
return Complex(real + c.real, imag + c.imag);
}
};
int main() {
Complex c1(1.0, 2.0);
Complex c2(3.0, 4.0);
Complex c3 = c1 + c2;
return 0;
}
在Complex类中重载了+运算符,使其可以对Complex对象进行相加操作。当使用c1 + c2时,会调用operator+函数。
动态多态(运行时多态):
- 虚函数(Virtual Functions)和覆盖(Overriding):
当一个类中定义了虚函数,编译器会为该类创建一个虚函数表(VTable),其中存储了该类的虚函数的地址。
每个包含虚函数的类的对象都包含一个虚函数指针(vptr),该指针指向该类的虚函数表。
当通过基类指针或引用调用虚函数时,程序会根据对象的实际类型,在运行时通过虚函数指针找到对应的虚函数表,并调用相应的虚函数。
#include <iostream>
class Shape {
public:
virtual void draw() {
std::cout << "Drawing a shape." << std::endl;
}
};
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing a circle." << std::endl;
}
};
int main() {
Shape* shapePtr = new Circle();
shapePtr->draw();
delete shapePtr;
return 0;
}
Shape类中定义了虚函数draw,Circle类继承自Shape并覆盖了draw函数。
当使用Shape* shapePtr = new Circle();创建一个Circle对象并使用Shape指针指向它,然后调用draw函数时,由于draw是虚函数,程序会在运行时根据shapePtr所指向对象的实际类型(Circle)调用Circle类的draw函数。
虚基类
在多重继承中,当一个派生类从多个基类继承,而这些基类又有共同的父类时,会出现二义性问题,即派生类会继承多个共同父类的副本。虚基类就是为了解决这个问题而引入的,它确保在派生类中只存在一个共同基类的副本。
定义方式:
在继承时使用 virtual 关键字将共同的基类声明为虚基类。
#include <iostream>
class Base {
public:
int value;
Base() : value(0) {
std::cout << "Base Constructor" << std::endl; }
};
class Derived1 : virtual public Base {
public:
Derived1() {
std::cout << "Derived1 Constructor" << std::endl; }
};
class Derived2 : virtual public Base {
public:
Derived2() {
std::cout << "Derived2 Constructor" << std::endl; }
};
class FinalDerived : public Derived1, public Derived2 {
public:
FinalDerived() {
std::cout << "FinalDerived Constructor" << std::endl; }
};
int main() {
FinalDerived obj;
// 不会产生二义性,因为 Base 只有一个副本
obj.value = 10;
return 0;
}
锁
线程锁的种类:互斥锁,条件锁,自旋锁,读写锁,递归锁
互斥锁
互斥锁是最基本的线程锁,用于保护共享资源,确保同一时间只有一个线程可以访问该资源。
当一个线程获取互斥锁后,其他线程尝试获取该锁时会被阻塞,直到锁被释放。
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void printMessage(const std::string& message) {
std::lock_guard<std::mutex> lock(mtx); // 使用 lock_guard 自动管理锁的获取和释放
std::cout << message << std::endl;
}
int main() {
std::thread t1(printMessage, "Hello from thread 1");
std::thread t2(printMessage, "Hello from thread 2");
t1.join();
t2.join();
return 0;
}
条件锁
条件锁通常与互斥锁一起使用,允许线程等待某些条件的发生。
线程可以在条件不满足时进入等待状态,当条件满足时,其他线程可以通知等待的线程继续执行。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
std::mutex mtx;
std::condition_variable cv;
std::queue<int> data_queue;
void producer() {
for (int i = 0; i < 10; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::unique_lock<std::mutex> lock(mtx);
data_queue.push(i);
std::cout << "Produced: " << i << std::endl;
cv.notify_one(); // 通知一个等待的线程
}
}
void consumer() {
while (true) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{
return!data_queue.empty(); }); // 等待直到队列不为空
int data = data_queue.front();
data_queue.pop();
lock.unlock();
std::cout << "Consumed: " << data << std::endl;
if (data == 9) break;
}
}
int main() {
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
return 0;
}
自旋锁
自旋锁不会使线程进入睡眠状态,而是在获取锁时循环等待,不断检查锁是否可用。
适用于锁的持有时间很短的情况,因为自旋锁不涉及线程的上下文切换。
#include <iostream>
#include <thread>
#include <atomic>
std::atomic_flag lock = ATOMIC_FLAG_INIT;
void printMessage(const std::string& message) {
while (lock.test_and_set(std::memory_order_acquire)) {
// 自旋等待
}
std::cout << message << std::endl;
lock.clear(std::memory_order_release);
}
int main() {
std::thread t1(printMessage, "Hello from thread 1");
std::thread t2(printMessage, "Hello from thread 2");
t1.join();
t2.join();
return 0;
}
读写锁(Read-Write Lock)
读写锁允许多个线程同时读共享资源,但写操作是独占的。
当有线程进行写操作时,其他线程的读和写操作都被阻塞;当有线程进行读操作时,其他线程可以继续读,但写操作被阻塞。
#include <iostream>
#include <thread>
#include <shared_mutex>
std::shared_mutex rwMutex;
void readData() {
std::shared_lock<std::shared_mutex> lock(rwMutex);