#C++ Day32 Basic Data Structure Chapter2 and C++ Generic Programming Day1  November 17 2025

Sequential List

Coding 

//Basic Data Structure Day1 Sequential List

//顺序表

#include <iostream>

using namespace std;

#define eleType int

struct SequentialList {//定义顺序表结构

eleType* elements;

int size; //顺序表当前的大小,元素的个数

int capacity; //顺序表的容量,就是数组的大小 

};

void intializeList(SequentialList* list, int capacity) {//初始化顺序表

list->elements = new eleType[capacity];

list->size = 0;

list->capacity = capacity;

}

void destroyList(SequentialList* list) {//删除整个顺序表

delete[] list->elements;

}

int main() {

return 0;

}

“C++ 泛型编程” 的标准英文表述是 C++ Generic Programming

补充说明:

  • 核心概念解析
    • Generic Programming(泛型编程):是一种编程范式,核心思想是 “编写与具体数据类型无关的代码,在使用时再指定具体类型”,从而实现代码的复用性、灵活性和类型安全性。
    • 在 C++ 中,泛型编程的主要实现手段是 Templates(模板),包括函数模板(Function Templates)和类模板(Class Templates),例如 std::vector、std::sort 等标准库组件均基于模板实现,支持不同数据类型(如 int、std::string)的通用操作。
  • 常见搭配与场景
    • 描述技术特性:Generic Programming in C++(C++ 中的泛型编程)、C++ Generic Programming Techniques(C++ 泛型编程技巧)。
    • 关联组件:C++ Template-based Generic Programming(基于 C++ 模板的泛型编程)、Generic Data Structures in C++(C++ 中的泛型数据结构)。
  • 与相关概念的区分
    有时容易与 “泛型” 混淆的是 “多态(Polymorphism)”,但二者本质不同:
    • 泛型编程(Generic Programming):编译期确定类型,通过模板生成特定类型的代码,属于 “静态多态”;
    • 面向对象的多态(OOP Polymorphism):运行期确定类型,通过虚函数实现,属于 “动态多态”。

例如,以下是 C++ 泛型编程(基于模板)的简单示例:

cpp

// 函数模板:通用的加法函数,支持任意可相加的类型

template <typename T>

T add(T a, T b) {

    return a + b;

}

int main() {

    int num1 = 3, num2 = 5;

    double num3 = 2.1, num4 = 3.5;

    std::cout << add(num1, num2) << std::endl;  // 编译期生成 int 版本的 add

    std::cout << add(num3, num4) << std::endl;  // 编译期生成 double 版本的 add

    return 0;

}

//C++ Generic Programming – Chapter 2 – Function Template – 2.1 Function Template Definition

//C++ 泛型变成 – 二、函数模板 2.1 函数模板定义 

#include <iostream>

using namespace std;

//函数模板

//就是建立一个通用的函数

//这个通用的函数 它的返回值和参数列表的类型 在定义的时候可以不指定 等到函数调用时再去指定

//相当于把形参类型和返回值的类型给它抽象出来 定义的时候不知道它的类型 只有在调用的时候才真正确定数据类型

/*

template <typename T>

函数的定义

T是通用类型

*/

int addInt(int a, int b) { //整型

int c = a + b;

return c;

}

double addDouble(double a, double b) {//浮点型

double c = a + b;

return c;

}

//这两个函数 除了类型不一样 其它都一样 框架一样

//小学提取公因式

//T是虚拟类型

template<typename T>//在前面加上函数模板定义 T变成自己定义的类型 编译就不会报错了

T add(T a, T b) {

T c = a + b;

return c;

}

int main() {

int a = 1, b = 2;

int c = addInt(a, b);

cout << c << endl;

double aa = 1.1, bb = 1.91;

double cc = addDouble(aa, bb);

cout << cc << endl;

return 0;

}

“自动类型推导” 的英文是 Automatic Type Deduction

补充说明:

  • 核心含义:指编程语言中由编译器或解释器根据变量的初始化值、表达式结果等信息,自动推断出变量或表达式数据类型的机制,无需开发者显式声明类型。
  • 常见应用场景:在 C++(如 auto 关键字)、Python(动态类型语言,天生支持类型推导)、Java(Java 10+ 的 var 关键字)、Go 等语言中广泛使用。
    • 示例(C++):auto num = 10;(编译器自动推导 num 为 int 类型)
    • 示例(Python):name = “Alice”(解释器自动推导 name 为字符串类型)
  • 相关术语
    • 若特指某类语言特性,可能会搭配具体关键字表述,如 auto Type Deduction(C++ 中基于 auto 的推导)、var Type Inference(Java/JavaScript 中基于 var 的推导,“Inference” 与 “Deduction” 在此语境下可通用,前者更侧重 “推断逻辑”,后者更侧重 “推导过程”)。

//C++ Generic Programming – Chapter 2 – 2.2.1 Function Template Calling – Automatic Type Deduction

//C++ 泛型编程 2.2.1 函数模板调用 – 自动类型推导

#include <iostream>

using namespace std;

//调用函数模板的方法有两种

//1.自动类型推导

//2.显式指定类型

//函数模板

//就是建立一个通用的函数

//这个通用的函数 它的返回值和参数列表的类型 在定义的时候可以不指定 等到函数调用时再去指定

//相当于把形参类型和返回值的类型给它抽象出来 定义的时候不知道它的类型 只有在调用的时候才真正确定数据类型

/*

template <typename T>

函数的定义

T是通用类型

*/

int addInt(int a, int b) { //整型

int c = a + b;

return c;

}

double addDouble(double a, double b) {//浮点型

double c = a + b;

return c;

}

//这两个函数 除了类型不一样 其它都一样 框架一样

//小学提取公因式

//T是虚拟类型

template<typename T>//在前面加上函数模板定义 T变成自己定义的类型 编译就不会报错了

T add(T a, T b) {

T c = a + b;

return c;

}

int main() {

int a = 1, b = 2;

int c = addInt(a, b);

cout << c << endl;

double aa = 1.1, bb = 1.91;

double cc = addDouble(aa, bb);

cout << cc << endl;

//自动类型推导

// 自动类型推导 编译器根据a和b的数据类型 去自己推导 并且找到合适的函数模板进行调用 只要没有不确定的数据类型就可以正常编译输出

// 好处就是把addInt和addDouble的函数变成一个函数去定义,这样就可以减少冗余的代码

//调用一个add,把a和b传进来

c=add(a, b);

cout << c << endl;

cc = add(aa, bb);

cout << cc << endl;

return 0;

}

//C++ Generic Programming – Chapter 2 – 2.2.2 Function Template Calling – Explicitly Specify the Type

//C++ 泛型编程 2.2.2 函数模板调用 – 显式指定类型

#include <iostream>

using namespace std;

//调用函数模板的方法有两种

//1.自动类型推导

//2.显式指定类型

//函数模板

//就是建立一个通用的函数

//这个通用的函数 它的返回值和参数列表的类型 在定义的时候可以不指定 等到函数调用时再去指定

//相当于把形参类型和返回值的类型给它抽象出来 定义的时候不知道它的类型 只有在调用的时候才真正确定数据类型

/*

template <typename T>

函数的定义

T是通用类型

*/

int addInt(int a, int b) { //整型

int c = a + b;

return c;

}

double addDouble(double a, double b) {//浮点型

double c = a + b;

return c;

}

//这两个函数 除了类型不一样 其它都一样 框架一样

//小学提取公因式

//T是虚拟类型

template<typename T>//在前面加上函数模板定义 T变成自己定义的类型 编译就不会报错了

T add(T a, T b) {

T c = a + b;

return c;

}

int main() {

int a = 1, b = 2;

int c = addInt(a, b);

cout << c << endl;

double aa = 1.1, bb = 1.91;

double cc = addDouble(aa, bb);

cout << cc << endl;

//自动类型推导

// 自动类型推导 编译器根据a和b的数据类型 去自己推导 并且找到合适的函数模板进行调用 只要没有不确定的数据类型就可以正常编译输出

// 好处就是把addInt和addDouble的函数变成一个函数去定义,这样就可以减少冗余的代码

//调用一个add,把a和b传进来

/*

c = add(a, b);

cout << c << endl;

cc = add(aa, bb);

cout << cc << endl;

*/

//显式指定类型

//显式指定类型就是在调用的时候直接告诉编译器 我这里的T是个什么类型 不需要编译器进行自动推导

c=add<int>(a, b); //这个<int>实际上就是程序员告诉编译器 接下来我要调用的这个函数 指定了T的这个类型是尖括号里面的这个int

cout << c << endl;

cc = add<double>(aa, bb);//我只要指定了这个类型 我这个add函数 只需要实现一个

cout << cc << endl;

//甚至以后出现了char类型

add<char>(‘a’, ‘b’);

return 0;

}

//C++ Generic Programming – Chapter 2 – 2.3.1 The Differences between Regular Functions – Regular Functions has Implicit Type Conversion

//C++泛型编程 第二章-函数模板 2.3.1 与普通函数区别 – 普通函数有隐式类型转换

#include <iostream>

using namespace std;

//对于普通函数 在实参变成形参的过程中 变量的类型实际上有可能产生隐式转换

int addInt(int a, int b) { //整型

int c = a + b;

return c;

}

double addDouble(double a, double b) {//浮点型

double c = a + b;

return c;

}

template<typename T>//在前面加上函数模板定义 T变成自己定义的类型 编译就不会报错了

T add(T a, T b) {

T c = a + b;

return c;

}

int main() {

int a = 1, b = 2;

//虽然这两个是整型变量 但是我依然可以调用addDouble这个函数 并且把a和b传进来 赋值给一个变量c

double c = addDouble(a, b);

cout << c << endl;

//正常运行 因为整型 a 作为传参的时候 在传的过程中强制转换成这个double 类型

//本来a和b都是整型 在传的过程中强制转换成这个double 类型

//普通函数在调用的时候 如果实参的参数类型和形参的参数类型不匹配 就可能发生隐式类型转换

return 0;

}

是的,在许多编程语言中(如 JavaScript、C++ 等),当函数调用时实参类型与形参类型不匹配时,会发生隐式类型转换(也称为自动类型转换)。

这种转换由编译器或解释器自动完成,目的是尝试让不匹配的类型能够兼容。

以 JavaScript 为例:

javascript

function add(a, b) {

  return a + b;

}

console.log(add(5, “10”));  // 输出 “510”,数字5被转换为字符串”5″,然后进行字符串拼接

console.log(add(“5”, 10));  // 输出 “510”,数字10被转换为字符串”10″

console.log(add(true, 5));  // 输出 6,布尔值true被转换为数字1

console.log(add(null, 5));  // 输出 5,null被转换为数字0

在 C++ 中也有类似的隐式转换:

cpp

#include <iostream>

using namespace std;

void printNumber(int num) {

    cout << “Number: ” << num << endl;

}

int main() {

    printNumber(‘A’);  // 字符’A’被转换为ASCII码值65

    printNumber(3.14); // 浮点数3.14被转换为整数3

    return 0;

}

隐式类型转换虽然方便,但也可能导致意外的结果,尤其是在 JavaScript 等弱类型语言中。因此,在编写代码时,最好显式地进行类型转换,以确保代码的可读性和正确性。

//C++ Generic Programming – Chapter 2 – Function Templates’ differences between regular functions  2.3.2 Function Templates Automatic Type Deduction  without Implicit Type Conversion

//C++ 泛型编程 – 第二章 – 函数模板 – 函数模板与普通函数的区别 2.3.2 函数模板自动类型推导无隐式类型转换

#include <iostream>

using namespace std;

//在函数模板进行自动类型推导时 无法进行隐式类型转换

int addInt(int a, int b) { //整型

int c = a + b;

return c;

}

double addDouble(double a, double b) {//浮点型

double c = a + b;

return c;

}

template<typename T>//在前面加上函数模板定义 T变成自己定义的类型 编译就不会报错了

T add(T a, T b) {

T c = a + b;

return c;

}

int main() {

int a = 1, b = 2;

int c = add(a, b);//这是自动类型推导

cout << c << endl;

double d = 2.5;

//int e = add(a, d);//这里出问题了 说没有与参数列表匹配的函数模板

// 错误!函数模板自动类型推导 无法进行 隐式类型转换

//a参数传入时 由于a是int类型 所以它把形参类型T推导成了 int

//当d参数传入时 因为它是double类型 所以它把形参类型T推导成double类型 

//然后这时候就冲突了 因为T不可能又是int又是double

//函数模板进行自动类型推导时 无法进行隐式类型转换

return 0;

}

//C++ Generic Programming – Chapter 2 – Function Templates’ differences between regular functions-2.3.3-Explicitly Specifying the Type with Implicit Type Conversion

//C++ 泛型编程 – 第二章 – 函数模板 – 函数模板与普通函数的区别 2.3.3 函数模板显式指定类型有隐式类型转换

#include <iostream>

using namespace std;

//在函数模板进行自动类型推导时 无法进行隐式类型转换

int addInt(int a, int b) { //整型

int c = a + b;

return c;

}

double addDouble(double a, double b) {//浮点型

double c = a + b;

return c;

}

template<typename T>//在前面加上函数模板定义 T变成自己定义的类型 编译就不会报错了

T add(T a, T b) {

T c = a + b;

return c;

}

int main() {

int a = 1, b = 2;

double d = 2.1;

//int e = add(a, d);//这里出问题了 说没有与参数列表匹配的函数模板

// 错误!函数模板自动类型推导 无法进行 隐式类型转换

//a参数传入时 由于a是int类型 所以它把形参类型T推导成了 int

//当d参数传入时 因为它是double类型 所以它把形参类型T推导成double类型 

//然后这时候就冲突了 因为T不可能又是int又是double

//函数模板进行自动类型推导时 无法进行隐式类型转换

int c = add<int>(a, d);//这样没问题 显式指定类型相当于这个T已经变成 int 

//T变成int之后 就算我这个是double 它也能自己进行隐式类型转换 

// 函数相当于明确地告诉编译器 请把我这个T推导成int 

//这里已经变成普通函数 那就沿用我们之前普通函数的规则:当传入的数据是什么类型不重要 它会在传参的过程中进行隐式的类型转换

//double c = add<double>(a, d);//也可以写 因为无论它转成什么类型 当我传一个类型进来 他都能变成隐式类型转换 根据自己的需要选择合适的数据类型就可以了

//函数模板的 【显式指定类型】 调用时的 【隐式类型转换】

cout << c << endl;

return 0;

}