-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1c29c16
commit c56082d
Showing
27 changed files
with
895 additions
and
2 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
--- | ||
title: c++4.1 final | ||
order: 4 | ||
category: | ||
- c++ | ||
--- | ||
|
||
<chatmessage avatar="../../../assets/emoji/dsyj.png" :avatarWidth="40"> | ||
|
||
在C++中,`final`关键字用于防止类或虚函数在派生类中被进一步继承或重写。 | ||
|
||
</chatmessage> | ||
|
||
#### 1. 阻止类的继承 | ||
|
||
```cpp | ||
class Base final { | ||
// 类内容 | ||
}; | ||
|
||
// 尝试继承Base会导致编译错误 | ||
class Derived : public Base { | ||
// 错误: Base类被标记为final,不能被继承 | ||
}; | ||
``` | ||
#### 2. 阻止虚函数的重写 | ||
```cpp | ||
class Base { | ||
public: | ||
virtual void foo() final { | ||
// 函数实现 | ||
} | ||
}; | ||
class Derived : public Base { | ||
public: | ||
void foo() override { | ||
// 错误: foo函数在Base类中被标记为final,不能被重写 | ||
} | ||
}; | ||
``` | ||
|
||
### 优点 | ||
|
||
1. **确保类行为的稳定性**: | ||
- 使用`final`可以防止派生类改变基类的行为,从而确保基类的行为在整个继承链中保持一致。 | ||
|
||
2. **优化性能**: | ||
- 编译器可以对`final`类或`final`虚函数进行更好的优化,因为它知道这些类或函数不会在派生类中被修改。 | ||
|
||
3. **设计意图明确**: | ||
- 使用`final`可以明确表达设计意图,即某些类不应该被继承或某些函数不应该被重写。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
--- | ||
title: c++4.显示默认/删除 | ||
order : 4 | ||
category: | ||
- c++ | ||
--- | ||
|
||
<chatmessage avatar="../../../assets/emoji/blzt.png" :avatarWidth="40" alignLeft > | ||
在 C++ 中,显式默认(explicit default)和显式删除(explicit delete)用于控制类的构造函数、拷贝构造函数、赋值运算符等成员函数的行为。 | ||
</chatmessage> | ||
|
||
在 C++ 中,显式默认(explicit default)和显式删除(explicit delete)用于控制类的构造函数、拷贝构造函数、赋值运算符等成员函数的行为。下面是这两种用法的示例: | ||
|
||
### 显式默认 | ||
|
||
`explicit default` 用于告诉编译器自动生成某些成员函数的默认实现。 | ||
|
||
|
||
```cpp | ||
#include <iostream> | ||
|
||
class MyClass { | ||
public: | ||
// 显式默认构造函数 | ||
MyClass() = default; | ||
|
||
// 显式默认拷贝构造函数 | ||
MyClass(const MyClass&) = default; | ||
|
||
// 显式默认拷贝赋值运算符 | ||
MyClass& operator=(const MyClass&) = default; | ||
|
||
// 显式默认析构函数 | ||
~MyClass() = default; | ||
|
||
void print() const { | ||
std::cout << "MyClass object\n"; | ||
} | ||
}; | ||
|
||
int main() { | ||
MyClass obj1; // 使用显式默认构造函数 | ||
MyClass obj2 = obj1; // 使用显式默认拷贝构造函数 | ||
obj1 = obj2; // 使用显式默认拷贝赋值运算符 | ||
obj1.print(); | ||
|
||
return 0; | ||
} | ||
``` | ||
|
||
示例中,`MyClass` 的构造函数、拷贝构造函数、拷贝赋值运算符和析构函数都被显式地指定为默认实现。这告诉编译器生成这些成员函数的默认版本。 | ||
|
||
### 显式删除 | ||
|
||
`explicit delete` 用于显式禁止某些成员函数的生成,使得这些函数不可用。 | ||
|
||
```cpp | ||
#include <iostream> | ||
|
||
class MyClass { | ||
public: | ||
// 显式删除拷贝构造函数 | ||
MyClass(const MyClass&) = delete; | ||
|
||
// 显式删除拷贝赋值运算符 | ||
MyClass& operator=(const MyClass&) = delete; | ||
|
||
// 默认构造函数 | ||
MyClass() = default; | ||
|
||
// 默认析构函数 | ||
~MyClass() = default; | ||
|
||
void print() const { | ||
std::cout << "MyClass object\n"; | ||
} | ||
}; | ||
|
||
int main() { | ||
MyClass obj1; // 使用默认构造函数 | ||
|
||
// MyClass obj2 = obj1; // 错误: 拷贝构造函数被删除 | ||
|
||
// MyClass obj3; | ||
// obj3 = obj1; // 错误: 拷贝赋值运算符被删除 | ||
|
||
obj1.print(); | ||
|
||
return 0; | ||
} | ||
``` | ||
|
||
示例中,`MyClass` 显式删除了拷贝构造函数和拷贝赋值运算符。这意味着对象不能被拷贝,尝试这样做将导致编译错误。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
--- | ||
title: c++5.联合类型局限 | ||
order : 5 | ||
category: | ||
- c++ | ||
--- | ||
|
||
<chatmessage avatar=" ../../assets/emoji/hx.png" :avatarWidth="40"> | ||
什么是联合类型? | ||
</chatmessage> | ||
|
||
<chatmessage avatar="../../../assets/emoji/blzt.png" :avatarWidth="40" alignLeft > | ||
联合类型(union)是C++中的一种数据结构,它允许在同一存储空间内存储不同类型的数据, | ||
但只能在一个时间点存储其中的一种类型。联合类型提供了一种节省内存的方式,但也有其局限性和使用注意事项。 | ||
</chatmessage> | ||
|
||
<chatmessage avatar=" ../../assets/emoji/hx.png" :avatarWidth="40"> | ||
和结构体很像啊!不过联合体更像是共享单车! | ||
</chatmessage> | ||
|
||
|
||
### 联合类型的定义与使用 | ||
|
||
```cpp | ||
#include <iostream> | ||
|
||
union MyUnion { | ||
int intValue; | ||
float floatValue; | ||
char charValue; | ||
}; | ||
|
||
int main() { | ||
MyUnion u; | ||
u.intValue = 42; | ||
std::cout << "intValue: " << u.intValue << std::endl; | ||
|
||
u.floatValue = 3.14; | ||
std::cout << "floatValue: " << u.floatValue << std::endl; | ||
|
||
u.charValue = 'a'; | ||
std::cout << "charValue: " << u.charValue << std::endl; | ||
|
||
// 注意:因为联合只能同时存储一种类型的值,所以只会打印最后一次赋值的内容 | ||
std::cout << "intValue: " << u.intValue << std::endl; // 不再有效 | ||
std::cout << "floatValue: " << u.floatValue << std::endl; // 不再有效 | ||
|
||
return 0; | ||
} | ||
``` | ||
|
||
### 联合类型的局限性 | ||
|
||
1. **同一时间只能存储一种类型的数据**: | ||
- 由于联合类型共享相同的存储空间,因此在给联合类型的某个成员赋值后,之前存储在该联合中的其他成员的数据将被覆盖。 | ||
|
||
2. **类型安全问题**: | ||
- 联合类型没有内置的机制来跟踪当前存储的数据类型,这可能会导致访问错误类型的数据,从而引发未定义行为。 | ||
|
||
3. **复杂数据类型的限制**: | ||
- 联合类型的成员不能是包含非平凡析构函数、非平凡拷贝构造函数或非平凡拷贝赋值运算符的复杂数据类型,例如C++标准库中的某些容器类。 | ||
- C++11之前,联合类型的成员不能是具有构造函数、析构函数或拷贝赋值运算符的类类型。C++11引入了受限联合类型(restricted unions),允许成员具有非平凡的默认构造函数,但依然不支持非平凡的析构函数或拷贝赋值运算符。 | ||
|
||
4. **对齐和填充问题**: | ||
- 由于不同数据类型的对齐要求,联合类型可能会导致内存填充,从而无法充分节省内存。 | ||
|
||
### 现代C++中的改进 | ||
|
||
在C++11及之后的标准中(C++ 17),引入了一些特性来增强联合类型的功能: | ||
|
||
1. **匿名联合类型**: | ||
- 匿名联合类型可以直接在类中定义,不需要显式命名,从而更简洁。 | ||
|
||
```cpp | ||
struct MyStruct { | ||
union { | ||
int intValue; | ||
float floatValue; | ||
char charValue; | ||
}; | ||
}; | ||
``` | ||
2. **类型安全联合类型**: | ||
- 使用 `std::variant` 替代传统的联合类型来获得类型安全的多态存储。 | ||
```cpp | ||
#include <variant> | ||
#include <iostream> | ||
int main() { | ||
std::variant<int, float, char> v; | ||
v = 42; | ||
std::cout << "int value: " << std::get<int>(v) << std::endl; | ||
v = 3.14f; | ||
std::cout << "float value: " << std::get<float>(v) << std::endl; | ||
v = 'a'; | ||
std::cout << "char value: " << std::get<char>(v) << std::endl; | ||
return 0; | ||
} | ||
``` | ||
|
||
`std::variant` 提供了类型安全的接口和更多的功能,比如类型访问和异常处理,从而避免了传统联合类型的许多局限性。 | ||
|
||
|
||
## 平凡类型和非平凡类型 | ||
|
||
平凡类型(trivial type)和非平凡类型(non-trivial type)。这些概念主要涉及对象的创建、销毁、复制和赋值的复杂性。 | ||
|
||
### 平凡类型(Trivial Type) | ||
|
||
平凡类型是指那些具有简单特性并且可以直接通过二进制复制进行创建、销毁、复制和赋值的类型。具体来说,一个类型如果满足以下条件,则称为平凡类型: | ||
|
||
1. **平凡默认构造函数**: | ||
- 默认构造函数不执行任何操作,并且可以通过简单的内存分配完成对象的初始化。 | ||
|
||
2. **平凡拷贝构造函数**: | ||
- 拷贝构造函数只执行简单的内存复制,不涉及任何复杂操作。 | ||
|
||
3. **平凡拷贝赋值运算符**: | ||
- 拷贝赋值运算符只执行简单的内存复制,不涉及任何复杂操作。 | ||
|
||
4. **平凡析构函数**: | ||
- 析构函数 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
--- | ||
title: c++6.聚合类型(aggregate type) | ||
order : 6 | ||
category: | ||
- c++ | ||
--- | ||
|
||
<chatmessage avatar=" ../../assets/emoji/hx.png" :avatarWidth="40"> | ||
什么是聚合类型? | ||
</chatmessage> | ||
|
||
<chatmessage avatar="../../../assets/emoji/blzt.png" :avatarWidth="40" alignLeft > | ||
通常指具有简单数据结构且不包含复杂成员函数的类型。 | ||
聚合类型的特点使得它们易于初始化,并且在许多情况下可以直接使用大括号进行列表初始化。 | ||
</chatmessage> | ||
|
||
### 聚合类型的定义 | ||
|
||
根据C++标准,一个类型如果满足以下所有条件,则称为聚合类型: | ||
|
||
![](..%2Fassets%2Fcpp001.png) | ||
|
||
### 示例 | ||
|
||
#### 简单结构体作为聚合类型 | ||
|
||
```cpp | ||
struct MyStruct { | ||
int x; | ||
double y; | ||
}; | ||
|
||
int main() { | ||
MyStruct s = {1, 2.0}; // 列表初始化 | ||
return 0; | ||
} | ||
``` | ||
在这个示例中,`MyStruct` 是一个聚合类型,因为它满足所有的条件:没有构造函数、所有成员都是公共的、没有虚函数、没有基类。 | ||
#### 非聚合类型示例 | ||
```cpp | ||
struct NonAggregate { | ||
private: | ||
int x; // 私有成员 | ||
public: | ||
NonAggregate() : x(0) {} // 用户提供的构造函数 | ||
virtual void foo() {} // 虚函数 | ||
}; | ||
struct Derived : NonAggregate { // 继承 | ||
double y; | ||
}; | ||
``` | ||
|
||
在这个示例中,`NonAggregate` 和 `Derived` 都不是聚合类型,因为它们不满足聚合类型的条件。 | ||
|
||
### 聚合类型的优点 | ||
|
||
1. **易于初始化**: | ||
- 聚合类型可以使用列表初始化(brace-enclosed initializer lists),使得对象的初始化更加简洁和直观。 | ||
|
||
```cpp | ||
struct Point { | ||
int x; | ||
int y; | ||
}; | ||
|
||
Point p = {1, 2}; // 列表初始化 | ||
``` | ||
2. **高效**: | ||
- 由于聚合类型通常只包含数据成员,不包含复杂的构造函数、析构函数或虚函数,它们的创建和销毁成本较低。 | ||
3. **直观的数据结构**: | ||
- 聚合类型非常适合用来表示简单的数据结构,如配置参数、坐标点、复数等。 | ||
### 使用聚合类型的注意事项 | ||
尽管聚合类型简单高效,但也有一些使用注意事项: | ||
1. **访问控制**: | ||
- 由于聚合类型的所有非静态数据成员必须是公共的,不能直接控制数据成员的访问权限,这在某些情况下可能会带来问题。 | ||
2. **扩展性**: | ||
- 聚合类型不支持继承和多态,因此在需要扩展功能时可能不适合。 | ||
3. **初始化顺序**: | ||
- 列表初始化的顺序必须与类型声明中数据成员的顺序一致,否则会导致编译错误或未定义行为。 |
Oops, something went wrong.