背景
示例代码
#include
using namespace std;
template <typename T>//模板说明
T myFunc(T size)//函数实现
{
cout << "size:" <return size;
}
int main(void)
{
myFunc(8);//自动推导调用
myFunc<float>((float)12.9);//显示调用
cout << "Hello!" << endl;
//system("pause");
return 0;
}
模板说明里面的类属参数在函数定义里面一定要使用,普通类型可以不使用
可以使用多个类型参数进行模板说明
#include
using namespace std;
template <typename T1, typename T2>//模板说明,两个类型参数
T2 mySort(T1 * array,T2 length)
{
T2 i = 0, j = 0;
T1 tmp = array[0];
for (i = 0; i < length; i++)
{
for (j = i + 1; j < length; j++)
{
if (array[i] < array[j])
{
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
}
return i;
}
template <typename T1,typename T2>//模板说明
T2 printArray(T1 *array,T2 length)//函数实现
{
T2 i = 0;
for (i = 0; i < length; i++)
{
cout << (int)array[i]<<""<< endl;
}
cout << endl;
return i;
}
int main(void)
{
char myArray[10] = {1,3,87,54,98,37,33,63,89,2};
int size = sizeof(myArray) / (*myArray);
mySort(myArray, size);
printArray(myArray, size);
cout << "Hello!" << endl;
//system("pause");
return 0;
}
结论:
函数模板不允许自动类型转化
普通函数能够进行自动类型转换
调用规则
1 函数模板可以像普通函数一样被重载
2 C++编译器优先考虑普通函数
3 如果函数模板可以产生一个更好的匹配,那么选择模板
4 可以通过空模板实参列表的语法限定编译器只通过模板匹配
/*
函数模板不允许自动类型转化
普通函数能够进行自动类型转换
*/
/*
1 函数模板可以像普通函数一样被重载
2 C++编译器优先考虑普通函数
3 如果函数模板可以产生一个更好的匹配,那么选择模板
4 可以通过空模板实参列表的语法限定编译器只通过模板匹配
*/
#include "iostream"
using namespace std;
int Max(int a, int b)
{
cout<<"int Max(int a, int b)"<return a > b ? a : b;
}
template<typename T>
T Max(T a, T b)
{
cout<<"T Max(T a, T b)"<return a > b ? a : b;
}
template<typename T>
T Max(T a, T b, T c)
{
cout<<"T Max(T a, T b, T c)"<return Max(Max(a, b), c);
}
void main()
{
int a = 1;
int b = 2;
cout<//当函数模板和普通函数都符合调用时,优先选择普通函数
cout<(a, b)<//若显示使用函数模板,则使用<> 类型列表
cout<3.0, 4.0)<//如果 函数模板产生更好的匹配 使用函数模板
cout<5.0, 6.0, 7.0)<//重载
cout<'a', 100)<//调用普通函数 可以隐式类型转换
system("pause");
return ;
}
编译器介绍
gcc(GNU C Compiler)编译器的作者是RichardStallman,也是GNU项目的奠基者。
什么是gcc:gcc是GNU Compiler Collection的缩写。最初是作为C语言的编译器(GNU C Compiler),现在已经支持多种语言了,如C、C++、Java、Pascal、Ada、COBOL语言等。
gcc主要特征
1)gcc是一个可移植的编译器,支持多种硬件平台
2)gcc不仅仅是个本地编译器,它还能跨平台交叉编译。
3)gcc有多种语言前端,用于解析不同的语言。
4)gcc是按模块化设计的,可以加入新语言和新CPU架构的支持
5)gcc是自由软件
gcc编译过程
Gcc *.c –o 1exe (总的编译步骤)
Gcc –E 1.c –o 1.i //宏定义 宏展开
Gcc –S 1.i –o 1.s
Gcc –c 1.s –o 1.o
Gcc 1.o –o 1exe
结论:gcc编译工具是一个工具链。。。。
GCC常用编译选项
选项 | 作用 |
---|---|
-o | 产生目标(.i、.s、.o、可执行文件等) |
-c | 通知gcc取消链接步骤,即编译源码并在最后生成目标文件 |
-E | 只运行C预编译器 |
-S | 告诉编译器产生汇编语言文件后停止编译,产生的汇编语言文件扩展名为.s |
-Wall | 使gcc对源文件的代码有问题的地方发出警告 |
-Idir | 将dir目录加入搜索头文件的目录路径 |
-Ldir | 将dir目录加入搜索库的目录路径 |
-llib | 链接lib库 |
-g | 在目标文件中嵌入调试信息,以便gdb之类的调试程序调试 |
GCC常用编译步骤
1.gcc -E hello.c -o hello.i(预处理)
2.gcc -S hello.i -o hello.s(编译)
3.gcc -c hello.s -o hello.o(汇编)
4.gcc hello.o -o hello(链接)
以上四个步骤,可合成一个步骤
gcc hello.c -o hello(直接编译链接成可执行目标文件)
gcc -c hello.c或gcc -c hello.c -o hello.o(编译生成可重定位目标文件)
Gcc编译多个文件
hello_1.h
hello_1.c
main.c
一次性编译
gcc hello_1.c main.c –o newhello
独立编译
gcc -Wall -c main.c -o main.o
gcc -Wall -c hello_1.c -o hello_fn.o
gcc -Wall main.o hello_1.o -o newhello
反汇编观察
命令: g++ -S 7.cpp -o 7.s
函数模板机制结论
类模板与函数模板的定义和使用类似,我们已经进行了介绍。 有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同,如下面语句声明了一个类:
类模板用于实现类所需数据的类型参数化
类模板在表示如数组、表、图等数据结构显得特别重要,
这些数据结构的表示和算法不受所包含的元素类型的影响
使用类模板声明对象的时候要显示指定形式参数的具体类型,以便C++编译器给对象分配具体的内存
单个类的语法
#include
using namespace std;
template <typename T>
class A
{
public:
A(int a = 0)
{
this->a = a;
}
void printA()
{
cout << a << endl;
}
protected:
private:
T a;
};
int main(void)
{
A<int> a1;
a1.printA();
A<int> a2(19);
a2.printA();
cout<<"Hello!"<return 0;
}
模板类作函数参数
#include
using namespace std;
template <typename T>
class A
{
public:
A(int a = 0)
{
this->a = a;
}
void printA()
{
cout << a << endl;
}
protected:
private:
T a;
};
//类模板 做函数参数
//参数 ,C++编译器 要求具体的类 所以所 要 A &a
void UseA(A<int> &a)
{
a.printA();
}
int main(void)
{
A<int> a1;
UseA(a1);
A<int> a2(19);
UseA(a2);
cout<<"Hello!"<return 0;
}
模板类派生时, 需要具体化模板类. C++编译器需要知道 父类的数据类型具体是什么样子的。要知道父类所占的内存大小是多少。只有数据类型固定下来,才知道如何分配内存。
从模板类派生普通类
#include
using namespace std;
template <typename T>
class A
{
public:
A(int a = 0)
{
this->a = a;
}
void printA()
{
cout << a << endl;
}
protected:
T a;
private:
};
class B:public A<int>
{
public:
B(int a = 10, int b = 20) : A<int>(a)
{
this->b = b;
}
void printB()
{
cout << "a:" << a << " b: " << b << endl;
}
protected:
private:
int b;
};
int main(void)
{
B b1(1, 2);
b1.printB();
cout<<"Hello!"<return 0;
}
从模板类派生模板类
#include
using namespace std;
template <typename T>
class A
{
public:
A(int a = 0)
{
this->a = a;
}
void printA()
{
cout << a << endl;
}
protected:
T a;
private:
};
template <typename T>
class C :public A
{
public:
C(T a, T c) :A(a)
{
this->c = c;
}
void printC()
{
cout << "a:" << a << "c:" << c << endl;
}
private:
T c;
protected:
};
int main(void)
{
C<int> c1(1, 2);
c1.printC();
cout<<"Hello!"<return 0;
}
类模板函数全部写在类的内部
#include
using namespace std;
template <typename T>
class Complex
{
friend Complex MySub(Complex c1, Complex c2)
{
Complex tmp(c1.a-c2.a,c1.b-c2.b);
return tmp;
}
friend ostream & operator<<(ostream & out, Complex & c)
{
out << c.a << " + " << c.b << "i" << endl;
return out;
}
public:
Complex(T a, T b)
{
this->a = a;
this->b = b;
}
Complex operator+(Complex & c2)
{
Complex tmp(a + c2.a,b + c2.b);
return tmp;
}
void printCom()
{
cout << a << " + " << b << "i" << endl;
}
protected:
private:
T a;
T b;
};
int main(void)
{
//需要把模板类 进行具体化以后 才能定义对象 C++编译器要分配内存
Complex<int> c1(1, 2);
Complex<int> c2(3, 4);
Complex<int> c3 = c1 + c2;
//c3.printCom();
cout << c3 << endl;
//滥用友元函数
{
Complex<int> c4 = MySub(c1, c2);
cout << c4 << endl;
}
cout<<"Hello!"<return 0;
}
类模板函数全写在类的外部,但在同一个cpp中
如果一个模板类具有友元函数,且该友元函数的形参包含模板类对象,则需要进行类模板和友元函数的前置声明。
需要注意的是:
#include
using namespace std;
template <typename T>//类的前置声明
class Complex;
template <typename T>//友元函数的前置声明
Complex MySub(Complex& c1, Complex& c2);//友元函数前置声明时不需要在函数名后面指定具体数据类型
template <typename T>
ostream& operator<<(ostream& out, Complex& c);//友元函数前置声明时不需要在函数名后面指定具体数据类型
template <typename T>
class Complex
{
friend Complex MySub(Complex& c1, Complex& c2); //在模板类里面声明友元函数的时候,需要在函数名后面紧跟具体的数据类型,比如
friend ostream & operator<<(ostream & out, Complex & c);//在模板类里面声明友元函数的时候,需要在函数名后面紧跟具体的数据类型,比如
/*
friend ostream & operator<<(ostream & out, Complex & c);
如果operator<<后面没有则会报错,所以模板类里面存在友元函数的时候,
除了进行友元函数的前置声明意外,还需要在模板类里面进行函数名数据类型具体化,
即指定具体的typename参数类型紧跟在函数名后面。
*/
public:
Complex(T a, T b);
Complex operator+(Complex & c2);
void printCom();
protected:
private:
T a;
T b;
};
/*
模板类的成员函数在类的外面实现的时候,
需要注意参数列表,函数名(类作用域)以及返回类型是否需要强行指定具体的数据类型,
以便编译器确定分配内存
*/
template <typename T>
Complex::Complex(T a, T b)
{
this->a = a;
this->b = b;
}
template <typename T>
Complex Complex::operator+(Complex & c2)
{
Complex tmp(a + c2.a, b + c2.b);
return tmp;
}
template <typename T>
void Complex::printCom()
{
cout << a << " + " << b << "i" << endl;
}
/*
友元函数在类的外部实现的时候,
不需要管函数名前面的类作用域以及函数名后面的具体数据类型,
只需要注意参数列表以及返回值是否需要指定数据类型即可
*/
template <typename T>
Complex MySub(Complex& c1, Complex& c2)
{
Complex tmp(c1.a - c2.a, c1.b - c2.b);
return tmp;
}
template <typename T>
ostream & operator<<(ostream & out, Complex & c)
{
out << c.a << " + " << c.b << "i" << endl;
return out;
}
int main(void)
{
//需要把模板类 进行具体化以后 才能定义对象 C++编译器要分配内存
Complex<int> c1(1, 2);
Complex<int> c2(3, 4);
Complex<int> c3 = c1 + c2;
//c3.printCom();
cout << c3 << endl;
//滥用友元函数
{
Complex<int> c4 = MySub<int>(c1, c2);//友元函数调用的时候,需要在函数名后面紧跟具体数据类型
cout << c4 << endl;
}
cout<<"Hello!"<return 0;
}
结论:不要滥用友元函数,一般友元函数只适用于重载
<<
或者>>
操作符。
类模板函数全写在类的外部,但在不同的.h和cpp中
由于模板的实现机制在本质上是两次编译,所以如果只在主程序里面包含头文件(类模板的声明),编译器不会自动寻找cpp文件里面的成员函数和友元函数的函数体。所以会出现找不到某个函数体的错误。只能是包含实现函数体的cpp文件,而cpp文件又包含了h文件,所以实质上是包含了类模板的声明以及类模板函数的实现,故业界都是将这两部分(.h和.cpp)写在同一个文件中,叫做hpp文件,只需要在提供的开源库里面包含该hpp文件,即可使用类模板。
#pragma once
#include
using namespace std;
template <typename T>
class Complex
{
friend ostream & operator<< (ostream &out, Complex &c3);
public:
Complex(T a, T b);
void printCom();
Complex operator+ (Complex &c2);
private:
T a;
T b;
};
#include
using namespace std;
#include "complex.h"
//构造函数的实现 写在了类的外部
template <typename T>
Complex::Complex(T a, T b)
{
this->a = a;
this->b = b;
}
template <typename T>
void Complex::printCom()
{
cout << "a:" << a << " b: " << b << endl;
}
template <typename T>
Complex Complex::operator+ (Complex &c2)
{
Complex tmp(a + c2.a, b + c2.b);
return tmp;
}
template <typename T>
ostream & operator<<(ostream &out, Complex &c3)
{
out << c3.a << " + " << c3.b << "i" << endl;
return out;
}
#include
using namespace std;
#include "complex.cpp"
void main()
{
//需要把模板类 进行具体化以后 才能定义对象 C++编译器要分配内存
Complex<int> c1(1, 2);
Complex<int> c2(3, 4);
Complex<int> c3 = c1 + c2;
cout << c3 << endl;
cout << "hello..." << endl;
return;
}
类模板—>实例化—>模板类
每一个模板类有自己的类模板数据成员,该模板类的所有对象共享一个static数据成员
和非模板类的static数据成员一样,模板类的static数据成员也应该在文件范围定义和初始化
每个模板类有自己的类模板的static数据成员副本
/*
编译器并不是把函数模板处理成能够处理任意类的函数
编译器从函数模板通过具体类型产生不同的函数
编译器会对函数模板进行两次编译
在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。
*/
#include
using namespace std;
template <typename T>
class AA
{
public:
static T m_a;
protected:
private:
};
template <typename T>
T AA::m_a = 0;
class AA1
{
public:
static int m_a;
protected:
private:
};
int AA1::m_a = 0;
class AA2
{
public:
static char m_a;
protected:
private:
};
char AA2::m_a = 0;
void main()
{
AA<int> a1, a2, a3;
a1.m_a = 10;
a2.m_a ++;
a3.m_a ++;
cout << AA<int>::m_a << endl;
AA<char> b1, b2, b3;
b1.m_a = 'a';
b2.m_a ++;
b2.m_a ++ ;
cout << AA<char>::m_a << endl;
//m_a 应该是 每一种类型的类 使用自己的m_a
cout<<"hello..."<"pause");
return ;
}
类模板的声明
int
要改变为float
或char
)改用一个自己指定的虚拟类型名(如上例中的numtype
)。template
template <class numtype> //注意本行末尾无分号
class Compare
{…}; //类体
类模板名<实际类型名> 对象名;
类模板名<实际类型名> 对象名(实参表列);
Compare<int> cmp;
Compare<int> cmp(3,7);
template
函数类型 类模板名<虚拟类型参数>::成员函数名(函数形参表列) {…}
class
或者typename
,如: template <class T1,class T2>
class someclass
{…};
在定义对象时分别代入实际的类型名,如:
someclass
7.和使用类一样,使用类模板时要注意其作用域,只能在其有效作用域内用它定义对象。
8.模板可以有层次,一个类模板可以作为基类,派生出派生模板类。
综述
1.模板是C++中类型参数化的多态工具,提供函数模板和类模板
2.模板定义从模板说明开始,类属参数必须在模板实现中至少使用一次
3.同一个类属参数可以用于多类模板
4.类属参数可用于函数形参,返回类型以及声明函数中的变量
5.模板由编译器根据实际的数据类型实例化,生成实际的可执行代码,从而得到模板函数和模板类
6.函数模板可以进行重载
7.类模板可以进行派生继承
工程中用到的容器
所有容器提供的都是值(value)语意,而非引用(reference)语意。容器执行插入元素的操作时,内部实施拷贝
动作。所以STL容器内存储的元素必须能够被拷贝
(必须提供拷贝构造函数
)。
案例
设计一个数组模板类( MyVector ),完成对int、char、Teacher类型元素的管理。
- 类模板定义
- 构造函数
- 拷贝构造函数
- 重载操作符
<< [] =
操作符- 从数组模板中进行派生
使用基础数据类型以及一般的自定义类对象作为容器元素
#pragma once
#include
using namespace std;
template <typename T>
class MyVector
{
public:
MyVector(int size = 0);//构造函数
MyVector(const MyVector & obj);//拷贝构造函数
~MyVector();//析构函数
T & operator[](int index);
MyVector & operator=(MyVector obj);
int getLen();
friend ostream & operator<< (ostream & out, const MyVector & obj);
protected:
private:
int m_len;
T *m_space;
};
#include "myvector.h"
template <typename T>
T & MyVector::operator[](int index)
{
return m_space[index];
}
template <typename T>
MyVector::MyVector(int size = 0)//构造函数
{
m_space = new T[size];
m_len = size;
}
template <typename T>
MyVector::MyVector(const MyVector & obj)//拷贝构造函数
{
m_len = obj.m_len;
m_space = new T[m_len];
for (int i = 0; i < m_len; i++)
{
m_space[i] = obj.m_space[i];
}
}
template <typename T>
MyVector::~MyVector()//析构函数
{
if (m_space != NULL)
{
delete[]m_space;
m_len = 0;
m_space = NULL;
}
}
template <typename T>
MyVector & MyVector::operator=(MyVector obj)
{
/*1.释放旧内存*/
if (m_space != NULL)
{
delete[]m_space;
m_space = NULL;
m_len = 0;
}
/*2.重新分配内存*/
m_space = new T[obj.m_len];
m_len = obj.m_len;
/*3.拷贝数据*/
for (int i = 0; i < m_len; i++)
{
m_space[i] = obj[i];
}
/*4.返回左值本身*/
return *this;
}
template <typename T>
int MyVector::getLen()
{
return m_len;
}
template <typename T>
ostream & operator<<(ostream & out, const MyVector & obj)
{
for (int i = 0; i < obj.m_len; i++)
{
cout << obj.m_space[i] << " ";
}
cout << endl;
return out;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#include "myvector.cpp"//注意包含的是cpp文件
using namespace std;
class Teacher
{
public:
Teacher()
{
age = 22;
strcpy(name, "Goopher");
}
Teacher(int age, char *name)
{
this->age = age;
strcpy(this->name,name);
}
void printTeacher()
{
cout << name << "," << age << endl;
}
protected:
private:
int age;
char name[32];
};
class Test1
{
public:
protected:
private:
int a;
};
class Test2
{
public:
protected:
private:
int a;
static int b;//static成员存储在全局区,不占类对象的内存模型
};
class Test3
{
public:
virtual void hello()//虚函数使得类对象具有VPTR指针,多占用一个指针的大小
{
}
protected:
private:
int a;
static int b;
};
class Test4
{
public:
virtual void hello()
{
}
virtual void hello01() = 0;//多个虚函数只对应一个VPTR指针(一个虚函数表)
protected:
private:
int a;
static int b;
};
class Test5
{
public:
virtual void hello()
{
}
virtual void hello01() = 0;
void printTest()//普通成员函数也不占据类对象的内存模型
{
}
protected:
private:
int a;
static int b;
};
class Test6
{
public:
virtual void hello()
{
}
//virtual void hello01() = 0;
void printTest()
{
}
void printTest01()//多个普通成员函数也不占据类对象的内存模型
{
}
protected:
private:
int a;
static int b;
};
int main(void)
{
/*初始化v1容器中的没一个对象并在初始化的时候逐个打印*/
MyVector<int> v1(10);
for (int i = 0; i < v1.getLen(); i++)
{
v1[i] = i + 1;
cout << v1[i] << " ";
}
cout << endl;
/*初始化v2容器中的没一个对象并在初始化以后使用重载<<的方式打印*/
MyVector<int> v2 = v1;
for (int i = 0; i < v2.getLen(); i++)
{
v2[i] = i*2 + 1;
}
cout </*使用类对象设置容器并打印*/
Teacher t1(31, "t1"), t2(32, "t2"), t3(33, "t3"), t4(34, "t4");
MyVector v3(4);
v3[0] = t1;
v3[1] = t2;
v3[2] = t3;
v3[3] = t4;
for (int i = 0; i < v3.getLen(); i++)
{
Teacher tmp = v3[i];
tmp.printTeacher();
}
cout<<"Hello!"<cout << sizeof(Test1)<cout << sizeof(Test2) << endl;
cout << sizeof(Test3) << endl;
cout << sizeof(Test4) << endl;
cout << sizeof(Test5) << endl;
cout << sizeof(Test6) << endl;
Test6 t6;
cout << sizeof(t6) << endl;
system("pause");
return 0;
}
优化后的Teacher类对象作为容器存储元素(类模板头文件和实现文件不变)
#define _CRT_SECURE_NO_WARNINGS
#include
#include "myvector.cpp"//注意包含的是cpp文件
using namespace std;
//1 优化Teacher类, 属性变成 char *panme, 购置函数里面 分配内存
//2 优化Teacher类,析构函数 释放panme指向的内存空间
//3 优化Teacher类,避免浅拷贝 重载= 重写拷贝构造函数
//4 优化Teacher类,在Teacher增加 <<
//5 在模板数组类中,存int char Teacher Teacher*(指针类型)
//=====>stl 容器的概念
class Teacher
{
public:
Teacher()
{
age = 22;
name = new char[1];
strcpy(name, "");
}
Teacher(int age, char *name)
{
this->age = age;
this->name = new char[strlen(name) + 1];
strcpy(this->name,name);
}
Teacher(const Teacher &obj)
{
age = obj.age;
name = new char[strlen(obj.name) + 1];
strcpy(name,obj.name);
}
~Teacher()
{
if (name != NULL)
{
delete[]name;
name = NULL;
age = 22;
}
}
void printTeacher()
{
cout << name << "," << age << endl;
}
friend ostream & operator<<(ostream & out, Teacher &obj);
Teacher & operator=(const Teacher & obj)
{
if (name != NULL)
{
delete[]name;
name = NULL;
age = 22;
}
name = new char[strlen(obj.name) + 1];
strcpy(name, obj.name);
age = obj.age;
return *this;
}
protected:
private:
int age;
char *name;
};
ostream & operator<<(ostream & out, Teacher &obj)
{
out << obj.name << "," << obj.age << endl;
return out;
}
int main(void)
{
/*使用类对象设置容器并打印*/
Teacher t1(31, "t1"), t2(32, "t2"), t3(33, "t3"), t4(34, "t4");
MyVector v3(4);
v3[0] = t1;
v3[1] = t2;
v3[2] = t3;
v3[3] = t4;
for (int i = 0; i < v3.getLen(); i++)
{
Teacher tmp = v3[i];
tmp.printTeacher();
}
cout<<"Hello!"<"pause");
return 0;
}
指针作为容器元素存储
#define _CRT_SECURE_NO_WARNINGS
#include
#include "myvector.cpp"//注意包含的是cpp文件
using namespace std;
//1 优化Teacher类, 属性变成 char *panme, 购置函数里面 分配内存
//2 优化Teacher类,析构函数 释放panme指向的内存空间
//3 优化Teacher类,避免浅拷贝 重载= 重写拷贝构造函数
//4 优化Teacher类,在Teacher增加 <<
//5 在模板数组类中,存int char Teacher Teacher*(指针类型)
//=====>stl 容器的概念
class Teacher
{
public:
Teacher()
{
age = 22;
name = new char[1];
strcpy(name, "");
}
Teacher(int age, char *name)
{
this->age = age;
this->name = new char[strlen(name) + 1];
strcpy(this->name,name);
}
Teacher(const Teacher &obj)
{
age = obj.age;
name = new char[strlen(obj.name) + 1];
strcpy(name,obj.name);
}
~Teacher()
{
if (name != NULL)
{
delete[]name;
name = NULL;
age = 22;
}
}
void printTeacher()
{
cout << name << "," << age << endl;
}
friend ostream & operator<<(ostream & out, Teacher &obj);
Teacher & operator=(const Teacher & obj)
{
if (name != NULL)
{
delete[]name;
name = NULL;
age = 22;
}
name = new char[strlen(obj.name) + 1];
strcpy(name, obj.name);
age = obj.age;
return *this;
}
protected:
private:
int age;
char *name;
};
ostream & operator<<(ostream & out, Teacher &obj)
{
out << obj.name << "," << obj.age << endl;
return out;
}
int main(void)
{
/*使用类对象设置容器并打印*/
Teacher t1(31, "t1"), t2(32, "t2"), t3(33, "t3"), t4(34, "t4");
MyVector v3(4);
v3[0] = &t1;
v3[1] = &t2;
v3[2] = &t3;
v3[3] = &t4;
for (int i = 0; i < v3.getLen(); i++)
{
Teacher *tmp = v3[i];
tmp->printTeacher();
}
cout << t1;
cout<<"Hello!"<"pause");
return 0;
}
总结:类模板实现了数据结构(具体数据类型)和算法的分离,真正的实现了泛型编程。