#C++ Day34 Basic Data Structure Chapter2 and C++ Generic Programming Day3 November 19 2025

//C++ Generic Programming – Chapter 3 – Class Templates – 3.2 Class Template Definition

//  C++ 泛型编程 -第三章 -类模版- 3.2 – 类模板定义

#include <iostream>

using namespace std;

//上节课已经实现了动态数组类 但是遗留了一个类型是整型的类冗余问题

//只需要建立类模板 减少冗余问题

/*

class DynamicArray

{

private:

    int* elements; 

    int size;      

public:

    DynamicArray(int n) : size(n)

    { 

        elements = new int[size];

    }

    ~DynamicArray()

    {

        delete[] elements;

    }

    int& operator[](int index) 

    {                           

        return elements[index]; 

    }

};

*/

template<class T>//可以写typename 也可以写class(这里的class跟下面的不是同一个意思) T是动态数组元素的虚拟类型

class DynamicArray

{

private:

    T* elements;//这里的int改成T

    //剩下的代表大小 索引的int不用改

    int size;

public:

    DynamicArray(int n) : size(n)

    {

        elements = new T[size];//在申请内存的时候 这里的int也改成T

    }

    ~DynamicArray()

    {

        delete[] elements;

    }

    T& operator[](int index)//在返回元素值时这里的int也改成T

    {

        return elements[index];

    }

};

int main()

{

    //int n = 10;

    //int* p = new int[n]; 

    //DynamicArray da(100);//在类模板实例化时我需要指定一个类型

    DynamicArray<double>da(100);

    da[1] = 3.1;

    da[9] = 4.2;

    cout << da[0] << ‘ ‘ << da[1] << endl;

    DynamicArray<char>dac(10);

    dac[0] = ‘A’;

    dac[1] = ‘C’;

    dac[2] = ‘M’;

    cout << dac[0] << dac[1] << dac[2] << endl;

    //类模板的定义和使用 好处:可以让代码进行复用 避免为不同的数据类型编写重复代码 提高了程序的通用性和灵活性

    return 0;

}

//C++ Generic Programming – Chapter 3 – Class Templates – 3.3 Member Function – 3.3.1 In – Class Definition

//C++ 泛型编程 -第三章 -类模版- 3.3 – 成员函数 3.3.1 类内定义

#include <iostream>

using namespace std;

//类模板的成员函数在类内的定义

template<class T>//可以写typename 也可以写class(这里的class跟下面的不是同一个意思) T是动态数组元素的虚拟类型

class DynamicArray

{

private:

    T* elements;//这里的int改成T

    //剩下的代表大小 索引的int不用改

    int size;

public:

    DynamicArray(int n) : size(n)

    {

        elements = new T[size];//在申请内存的时候 这里的int也改成T

    }

    ~DynamicArray()

    {

        delete[] elements;

    }

    T& operator[](int index)//在返回元素值时这里的int也改成T 这里T是返回值

        //这就是成员函数了 和普通成员函数没有什么很大的区别 只需要把需要替换的类型替换成虚拟类型就可以了

    {//和我们之前学过的函数模板很像 甚至除了定义位置以外 其他都是一模一样的  这个模板的定义在外面 成员函数函数的定义是在类里面

        return elements[index];

    }

    //类模板的成员函数的实现 其他实现都和普通类一模一样 只不过在涉及到这个虚拟类型有关的传参或者返回值的时候 需要替换成我们定义的虚拟类

    // 

    //更新第 index个索引的元素,把它的值改成 value 

    //int

    void update(int index, T value) {//这里T是传参 不要把T写成int 写成int后编译器不会报错 但是逻辑本身也是错的

        elements[index] = value; //如果把int写成T 会触发强制类型转换

//想办法把这些类内定义的函数抽到类外去定义

    }

};

int main()

{

    DynamicArray<char> dac(100);

    dac[56] = ‘h’;

    cout << dac[56] << endl;

    dac.update(56, ‘u’);

    cout << dac[56] << endl;

    return 0;

}

//C++ Generic Programming – Chapter 3 – Class Templates – 3.3 Member Function – 3.3.2 Out-of-Class Definition

v

#include <iostream>

using namespace std;

//类模板的成员函数在类内的定义

template<class T>//可以写typename 也可以写class(这里的class跟下面的不是同一个意思) T是动态数组元素的虚拟类型

class DynamicArray

{

private:

    T* elements;//这里的int改成T

    //剩下的代表大小 索引的int不用改

    int size;

public:

    //把成员函数放到类外实现

    // 实现删掉

    //1、保留声明

    DynamicArray(int n); /* : size(n)

    {

        elements = new T[size];//在申请内存的时候 这里的int也改成T

    }*/

    //析构函数也按步骤实现一下

    ~DynamicArray();/*

    {

        delete[] elements;

    }*/

    T& operator[](int index);//在返回元素值时这里的int也改成T 这里T是返回值

        //这就是成员函数了 和普通成员函数没有什么很大的区别 只需要把需要替换的类型替换成虚拟类型就可以了

    //{//和我们之前学过的函数模板很像 甚至除了定义位置以外 其他都是一模一样的  这个模板的定义在外面 成员函数函数的定义是在类里面

      //  return elements[index];

   // }//这里不注释也可以 搬到类外

    //类模板的成员函数的实现 其他实现都和普通类一模一样 只不过在涉及到这个虚拟类型有关的传参或者返回值的时候 需要替换成我们定义的虚拟类

    // 

    //更新第 index个索引的元素,把它的值改成 value 

    //int

    void update(int index, T value); /* {//这里T是传参 不要把T写成int 写成int后编译器不会报错 但是逻辑本身也是错的

        elements[index] = value; //如果把int写成T 会触发强制类型转换

        //想办法把这些类内定义的函数抽到类外去定义

    }*/

    //这样就只剩下成员函数的定义和成员函数的声明了 很干净  具体函数的实现就到类外面去了

};

//2、拷贝声明

//3、加作用域

//4、拷贝实现

//5、模板参数列表声明

//6、指定虚拟类型

template<class T>

DynamicArray<T>::DynamicArray(int n) : size(n)//加上作用域 类名和两个冒号 并把之前的部分拷贝过来

{

    elements = new T[n];//在申请内存的时候 这里的int也改成T

}

template<class T>

DynamicArray<T>::~DynamicArray() {

    delete[] elements;

}

template<class T>

T& DynamicArray<T>::operator[](int index) {//规定 这个作用域要加在 函数名和返回值之间

    return elements[index];

}

template<class T>

void DynamicArray<T>::update(int index, T value) {

    elements[index] = value;

}

int main()

{

    DynamicArray<char> dac(100);

    dac[56] = ‘h’;

    cout << dac[56] << endl;

    dac.update(56, ‘u’);

    cout << dac[56] << endl;

    return 0;

}

//C++ Generic Programming – Chapter 3 – Class Templates – 3.3 Member Function – 3.3.3 Creation Timing

//C++ 泛型编程 -第三章 -类模版- 3.3 – 成员函数 3.3.3 创建时机

//类模板中成员函数的创建时机

#include <iostream>

using namespace std;

//对于普通类中的成员函数 在一开始时就已经创建出来了

//类模板的成员函数 会在调用时才会去创建

class Player {

public:

void run() {

cout << “跑步” << endl;

}

};

class Ball {

public:

void drop() {

cout << “下落” << endl;

}

};

template<class T>

class Test {

T obj; //编译不出错 说明对于编译器来讲 obj是啥都不知道

public:

void move1() { //所以这两个函数在一开始时根本没有创建出来

obj.run();

}

void move2() {//所以这两个函数在一开始时根本没有创建出来

obj.drop();

}

};

int main() {

Test<Player> test1;

test1.move1();

//test1.move2();//error C2039: ‘drop’: is not a member of ‘Player’

Test<Ball> test2;

//test2.move1();//它是Ball Ball没有run 只有drop

test2.move2();

//这也就验证了 这个类模板的成员函数 当我没有调用它之前 实际上并没有生成出来 这就是类模板成员函数的创建时机

return 0;

}

//C++ Generic Programming – Chapter 3 – Class Templates – 3.4 Parameter Passing for Object Functions

//C++ 泛型编程 -第三章 -类模版-3.4 对象的函数传参

#include <iostream>

using namespace std;

//当类模板实例化出来的对象作为函数参数时如何进行传递

template<class NameType, class HpType>//两个虚拟类型需要加上声明

class Hero {

public:

Hero(NameType name, HpType hp) {//写一个构造函数 传两个变量进来 类型是NameType和HpType

this->m_name = name; //赋值

this->m_hp = hp;

}

private:

NameType m_name;//虚拟类型1

HpType m_hp;//虚拟类型2

};

//1、直接指定类型

void test1(Hero<string, double>& h) { //加个引用 因为要拷贝一份新的 就是它本身

}

//2、参数模板化

template<typename T1, typename T2>

void test2(Hero<T1, T2>& h) { //加个引用 因为要拷贝一份新的 就是它本身

//把参数类型变成T1 跟T2 

//然后因为是虚拟类型 所以要加上一个模板参数列表的声明 这就是我们之前学过的函数模板

}

//3、类模板化

template<typename T>//只有一个类了

void test3(T& h) { //加个引用 因为要拷贝一份新的 就是它本身

}

//三种方法都有应用场景  怎么使用看你实际的需要

int main() {

//函数里面通过类模板 实例化一个对象

Hero<string, double> h(“宋江”, 100.0);//这个Hero类有两个模板参数

test1(h);//函数的实际参就是这个h

test2(h);

test3(h);

return 0;

}

//C++ Generic Programming – Chapter 3 – Class Templates – 3.5 Class Template Inheritance

// C++ 泛型编程 – 第三章 – 类模版 – 3.5 类模板的继承

#include <iostream>

using namespace std;

//类模板的继承 一旦你写错了 编译器会直接告诉你 错的很明确

template<class NameType, class HpType>

class Hero {

public:

Hero(NameType name, HpType hp) {

this->m_name = name; 

this->m_hp = hp;

}

private:

NameType m_name;

HpType m_hp;

};

//这个Hero类 它是个父类 并且是个类模板 那我现在需要写个子类去继承它

//class HeroSon : public Hero<string,double>{ //对于类模板来说 当我们实例化对象的时候 需要显示指定参数 继承也一样

//

//};

template<class T1,class T2,class T3>

class HeroSon : public Hero<T1, T2> { //子类想用的时候 我还是希望这两个参数进行模板化 所以需要用虚拟类型来替代掉

//HeroSon子类里可能需要有虚拟类型

T3 a;

//这节课也可以自己敲代码 通过编译器的指引把代码敲对

};

int main() {

return 0;

}