C++基础知识

虚析构函数

  在 C++ 中,虚析构函数(virtual destructor)是在基类中声明并使用 virtual 关键字修饰的析构函数。
  虚析构函数在处理基类指针指向派生类对象时非常有用。当使用基类指针来删除一个指向派生类对象的实例时,如果基类的析构函数不是虚拟的,只会调用基类的析构函数,而不会调用派生类的析构函数。这可能导致派生类对象中的资源无法正确释放,造成内存泄漏。
  通过将基类的析构函数声明为虚拟的,可以确保在删除基类指针时正确调用派生类的析构函数,从而正确释放派生类对象的资源。下面是一个使用虚析构函数的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<string>
using namespace std;

class base{
public:
virtual ~base(){
cout<<"base's ~";
};
};

class child:public base{
public:
~child(){
cout<<"child's~";
}
};

int main(){
base* p = new child();
delete p;
return 0;
}

for循环遍历迭代器

1
2
3
4
5
6
7
8
9
10
11
12
#include<iostream>
#include<list>
int main(){
std::list<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
for(auto &i:a ){
std::cout<<i<<std::endl;
}
return 0;
}

cmake初级

文件夹设置
├── CMakeLists.txt
├── sylar
│ ├── CMakeLists.txt
│ ├── main.cpp

第一个CMakeLists.txt

1
2
3
4
5
6
7
cmake_minimum_required(VERSION 3.12)
project(sylar)

set(CMAKE_CXX_STANDARD 14)

add_subdirectory(sylar)
# add_executable(sylar sylar/main.cpp)

第二个CMakeLists.txt

1
add_executable(sylar main.cpp)

可变参数列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <cstdarg>

// 可变参数列表的函数定义
void print(int count, ...) {
va_list args;
va_start(args, count);

for (int i = 0; i < count; ++i) {
int value = va_arg(args, int);
std::cout << value << std::endl;
}

va_end(args);
}

int main() {
print(6,1,7,9,2,3,4);
return 0;
}

操作符重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
// 自定义类 MyClass
class MyClass {
public:
int data;
MyClass(int value) : data(value) {}

friend std::ostream& operator<<(std::ostream& os, const MyClass& obj) {
os << "MyClass: " << obj.data;
return os;
}
};

int main() {
MyClass obj(42);
std::cout << obj << std::endl;

return 0;
}

单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>

class Singleton {
private:
// 私有的静态成员变量,用于存储单例实例
static Singleton* instance;

// 私有的构造函数,防止外部直接实例化对象
Singleton() {}

public:
// 静态成员函数,用于获取单例对象的唯一实例
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}

// 示例成员函数
void showMessage() {
std::cout << "Hello from Singleton!" << std::endl;
}
};

// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;

int main() {
Singleton* instance1 = Singleton::getInstance();
Singleton* instance2 = Singleton::getInstance();

// instance1和instance2指向相同的对象
instance1->showMessage(); // 输出: Hello from Singleton!
instance2->showMessage(); // 输出: Hello from Singleton!

// 清理单例对象
delete instance1;
instance1 = nullptr;

return 0;
}

模板类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>

template <class F, class T>
class LexicalCast {
public:
T operator()(const F& v) {
return boost::lexical_cast<T>(v); //将T转换为int
}
};

int main() {
LexicalCast<std::string, int> stringToInt;
int num = stringToInt("12345");
std::cout << "Converted integer: " << num << std::endl;

LexicalCast<double, std::string> doubleToString;
std::string str = doubleToString(3.14159);
std::cout << "Converted string: " << str << std::endl;

return 0;
}

static 关键词

在 C++ 头文件(.h)中定义的静态函数,在对应的实现文件(.cpp)中不需要再使用 static 关键词修饰。

当在头文件中声明静态函数时,使用 static 关键词是为了将函数的作用域限制在当前文件中,避免与其他文件中同名的函数产生冲突。这样做是因为头文件通常会被多个源文件包含,如果在头文件中使用 static 修饰符,每个包含该头文件的源文件都会有一个独立的静态函数副本,可能导致链接错误。

而在实现文件中,已经处于单个文件的作用域中,不需要再次使用 static 关键词来限制函数的作用域。实现文件中的静态函数的定义只需要与头文件中的函数声明相匹配即可。

因此,头文件中的静态函数声明不需要再使用 static 关键词修饰,而在对应的实现文件中,只需要提供静态函数的定义即可。这样可以保持函数在整个程序中的唯一性,并正确地与其他文件中的代码进行链接。

在 C++ 中,# 是一种预处理操作符,称为字符串化操作符(stringizing operator)。它用于将宏参数转换为字符串字面值。