Procházet zdrojové kódy

feat: 添加模板和泛型基础

NiceTry12138 před 10 měsíci
rodič
revize
58193bc6a1
2 změnil soubory, kde provedl 144 přidání a 0 odebrání
  1. binární
      cpp/现代C++/Image/006.png
  2. 144 0
      cpp/现代C++/现代C++.md

binární
cpp/现代C++/Image/006.png


+ 144 - 0
cpp/现代C++/现代C++.md

@@ -1121,3 +1121,147 @@ void process5(const shared_ptr<TestCls>&);	// 比 process4 好一点,用的引
 ### 内存机制
 
 [之前写过C++的内存机制](../内存机制.md)
+
+## 泛型
+
+[之前有写过一些模板相关内容](../泛型与模板.md)
+
+### 模板的实例化
+ 
+- 模板类成员
+  - 普通成员:使用与主模板相同类型模板参数
+    - 数据成员(变量或常量)
+    - 成员函数
+    - 静态成员(数据或函数)
+    - 成员类型别名
+    - 成员类型
+  - 成员模板(使用与主模板不同的类型模板)
+    - 成员模板不能定义**虚函数**,模板实例化会导致链接器不断为虚表增加虚函数增项
+
+```cpp
+#include <iostream>
+#include <stdexcept>
+
+template <typename T, size_t N = 10> // N 是默认模板参数
+class Array {
+public:
+    // 成员类型别名
+    using value_type = T;
+    using reference = T&;
+    using const_reference = const T&;
+    using size_type = size_t;
+    using iterator = T*;           // 简化迭代器实现
+    using const_iterator = const T*;
+
+    // 静态成员
+    static constexpr size_type static_size = N;
+
+    // 构造函数
+    Array() = default;
+
+    // 成员函数
+    reference operator[](size_type pos) {
+        if (pos >= N) {
+            throw std::out_of_range("Index out of range");
+        }
+        return m_data[pos];
+    }
+
+    iterator begin() noexcept { return m_data; }
+    const_iterator cbegin() const noexcept { return m_data; }
+    iterator end() noexcept { return m_data + N; }
+    const_iterator cend() const noexcept { return m_data + N; }
+
+    size_type size() const noexcept { return N; }
+    bool empty() const noexcept { return N == 0; }
+
+    // 静态成员函数
+    static constexpr size_type max_size() noexcept {
+        return static_size;
+    }
+
+	// 错误 成员模板不可以是虚函数
+	template<typename U>
+    virtual void add() {
+        std::cout << "add " << typeid(U).name() << std::endl;
+    }
+
+private:
+    // 数据成员
+    value_type m_data[N] = {}; // 内置数组存储元素
+};
+
+// 静态成员的类外定义(可选)
+template <typename T, size_t N>
+constexpr typename Array<T, N>::size_type Array<T, N>::static_size;
+
+// 示例使用
+int main() {
+    Array<int, 5> arr;
+    // 通过迭代器访问
+    for (auto& elem : arr) {
+        elem = 5;
+    }
+    // 使用成员类型别名
+    Array<int>::value_type x = 10;
+    // 访问静态成员
+    std::cout << "Max size: " << Array<int, 5>::max_size() << std::endl;
+    try {
+        arr[6] = 10; // 抛出异常
+    }
+    catch (const std::exception& e) {
+        std::cerr << "Error: " << e.what() << std::endl;
+    }
+    return 0;
+}
+
+```
+
+![](Image/006.png)
+
+C++ 模板是一中编译时机制,在编译时生成具体的代码,使用实参将模板定义实例化为具体的类型或函数
+
+- C++支持两种模板
+  - 类模板
+  - 函数模板
+
+模板实例化时编译器会对实参类型进行检查,确保实参符合对模板参数的操作要求
+
+- C++模板参数支持两种
+  - 类型参数,可隐式约束,也可以显示约束
+  - 值参数,编译时常量,或 `constexpr` 函数。不同值参数时不同类型(不允许时值浮点数、类对象,编译器不能确定值)
+  - 可以为模板参数提供默认值
+
+```cpp
+template <typename T, size_t N = 10> // N 是默认模板参数
+class Array {}
+
+Array<int, 5> arr;
+```
+
+关于类型别名,优先使用 `using` 而不是 `typedef`,因为 `using` 支持模板,但是 `typedef` 不支持
+
+```cpp
+typedef svector = vector<string>;
+
+using svector = vector<string>;
+
+template<typename T>
+using myvector = vector<T, Allocator<T>>;
+```
+
+
+
+
+- 数据成员:只要类型被使用,编译i其就会根据其数据成员,生成对应类型结构
+- 函数成员:选择性实例化
+  - 非虚函数:如果实际调用到,则会生成代码;如果没有调用到,则不生成
+  - 虚函数:无论是否调用,总会生成代码,因为运行时很可能会用到
+
+如果某些模板方法没有被调用,即使包含编译错误,也会被忽略,这就是**隐藏编译错误**
+
+也可以使用强制实例化模板,来强制要求编译所有模板函数成员,排除所有编译错误,无论是否调用到
+
+```cpp
+template class Array<int>;
+```