程序员面试秘笈之⑩"/>
C和C++程序员面试秘笈之⑩
本系列博客基于董山海的<C和C++程序员面试秘笈>,旨在记录,欢迎交流,可联系 zywang@shu.edu !
第10章:泛型编程
文章目录
- 1、面试题1
- 2、面试题2
- 3、面试题3
- 4、面试题4
- 5、面试题5
1、面试题1
泛型编程:编写完全一般化并可重复使用的算法,其效率与针对特定数据类型而设计的算法一致。所谓泛型,是指具有在多种数据类型上皆可操作的含义。
int max(int a, int b) { //参数和返回值为int类型return a > b ? a : b;
}
//
float max(float a, float b) { //参数和返回值为float类型return a > b ? a : b;
}
//
double max(double a, double b) { //参数和返回值为double类型return a > b ? a : b;
}
重载函数,我们可以使用模板:
template <class T> //class 也可用 typename 代替
T max(T a, T b) { //参数和返回值类型都是 Treturn a > b ? a : b;
}
//这里的 class 不代表对象的类,而是类型
2、面试题2
函数模板与类模板的基本概念和区别:
函数模板:抽象的函数定义,代表一类的同构函数。通过用户提供的具体参数,C++编译器在编译时刻能够将模板实例化,根据同一模板创建出不同的具体函数。
函数模板:
t e m p l a t e < T Y P E L I S T , A R G L I S T > F u n c t i o n D e f i n i t i o n template<TYPE_{LIST},ARG_{LIST}>Function_{Definition} template<TYPELIST,ARGLIST>FunctionDefinition
其中, F u n c t i o n D e f i n i t i o n Function_{Definition} FunctionDefinition为函数定义; T Y P E L I S T TYPE_{LIST} TYPELIST为类型参数表; A R G L I S T ARG_{LIST} ARGLIST为变量表,相当于形式参数。
类模板:
更高层次的抽象类定义,用于使用相同代码创建不同的类模板的定义与函数模板的定义类似,只是把函数模板中的函数定义部分换做类说明,并对类的成员函数进行定义。
template<<模板参数表>>
class<类模板名> {<类模板定义体>;
};
如:定义一个表示平面的点(point)类,这个类有两个成员变量,分别表示横坐标和纵坐标,并且这两个坐标的类型可以是 int、doubli、float等类型。因此可能写出类似 Point_int_int、Point_float_int、Point_float_float等这样的类。通过类模板我们只需要写一个类。
#include <iostream>
using namespace std;
//
template <class T1, class T2>
class Point_T {
public:T1 a;T2 b;Point_T() :a(0), b(0) {} //默认构造函数Point_T(T1 ta, T2 tb) :a(ta), b(tb) {} //带参数的构造函数Point_T<T1, T2>& operator=(Point_T<T1, T2>&pt); //赋值函数friend Point_T<T1, T2>operator+(Point_T<T1, T2>&pt1, Point_T<T1, T2>&pt2); //重载 +
};
//
template <class T1,class T2> //赋值函数
Point_T<T1, T2>& Point_T<T1,T2>::operator=(Point_T<T1, T2> &pt) {this->a = pt.a;this->b = pt, b;return *this;
}
//
template <class T1, class T2> //重载+
Point_T<T1, T2>operator +(Point_T<T1, T2> &pt1, Point_T<T1, T2>&pt2) {Point_T<T1, T2> temp;temp.a = pt1.a + pt2.a; //结果对象中的 a 和 b 分别为两个参数对象的各自 a 与 b 之和temp.b = pt1.b + pt2.b;return temp;
}
//
template <class T1,class T2> //重载输出流操作符
ostream& operator<<(ostream& out, Point_T<T1, T2>& pt) {out << "(" << pt.a << ","; //输出(a,b)out << pt.b << ")"; return out;
}
//
int main() {Point_T<int, int> intPt1(1, 2); //T1 和 T2 都是intPoint_T<int, int> intPt2(3, 4); //T1 和 T2 都是intPoint_T<float, float> floatPt1(1.1f, 2.2f); //T1 和 T2 都是floatPoint_T<float, float> floatPt2(3.3f, 4.4f); //T1 和 T2 都是float//Point_T<int, int> intTotalPt;Point_T<float, float> floatTotalPt;//intTotalPt = intPt1 + intPt2; //类型为 Point_T<int,int> 的对象相加floatTotalPt = floatPt1 + floatPt2; //类型为 Point_T<float,float> 的对象相加//cout << intTotalPt << endl; //输出 Point_T<int,int> 的对象cout << floatTotalPt << endl; //输出 Point_T<float,float> 的对象system("pause");return 0;
}
函数模板、模板函数、类模板、模板类:
函数模板:重点是模板,表示一个模板,用于生产函数;
模板函数:重点是函数;
类模板:重点是模板,用于生产类,如 Point_T 是类模板;
模板类:一个模板生成的类,如 Point_T<int, int>
3、面试题3
使用模板的缺点:
缺点:不当地使用模板会导致代码膨胀,即二进制代码臃肿而松散,会影响程序的运行效率;
解决:把 C++ 模板中与参数无关的代码分离出来;
4、面试题4
模板的特化:函数模板的特化和类模板的特化
(1)函数模板的特化:当函数模板需要对某些类型进行特别处理时,称为函数模板的特化。
bool IsEqual(T t1, T t2) {return t1 == t2;
}
//
int main() {char str1[] = "Hello";char str2[] = "Hello";cout << IsEqual(1, 1) << endl;cout << IsEqual(str1, str2) << endl;return 0;
}
代码 cout<<IsEqual(str1,str2)<<endl 比较字符串是否相等。由于 max 函数模板只是简单地比较传入参数的值,即两个指针是否相等。这与初衷不符合,因此 max函数模板需要对 char* 类型进行特别处理,即特化:
template <>
bool IsEqual(char* t1, char* t2) {return strcmp(t1, t2) == 0;
}
(2)类模板的转化:
template <class T>
class compare {
public:bool IsEqual(T t1, T t2) {return t1 == t2;}
};
//
int main() {char str1[] = "Hello";char str2[] = "Hello";compare<int> c1;compare<char *> c2;cout << c1.IsEqual(1, 1) << endl;cout << c2.IsEqual(str1, str2) << endl;return 0;
}
这边进行类模板的特化:
template <class T>
class compare<char *> { //特化(char *)
public:bool IsEqual(char* t1, char* t2) {return strcmp(t1,t2)== 0;}
};
5、面试题5
设计一个公共的 class,通过他的接口可以对任意类型的数组排序。
说明:
关键在于:对于任何类型的数组进行排序。以往我们是使用不同类型参数的重载函数来完成。
template <class T>
class Test {
public:static void Sort(T *array, int len.bool(*Compare)(T& a, T& b)) {T temp; //用于冒泡排序的交换assert(len >= 1); //len 必须大于1for (int i = 0; i < len - 1; i++) { //冒泡排序for (int j = len - 1; j > i; j--) {//使用Compare函数指针的方式进行比较if (Compare(array[j], array[j - 1])) { //根据升序或降序需要进行交换temp = array[j - 1];array[j - 1] = array[j];array[j] = temp;}}}}
};
- Sort 成员为 static,可用 Test::Sort 访问;
- Sort 的第3个参数Compare是一个函数指针,它指向两个函数模板的一种。
template <class T>
bool ascend(T& a, T& b) {return a < b ? true : false;
}template <class T>
bool descend(T& a, T& b) {return a > b ? true : false;
}
我们可以使用 Test 类的 Sort 函数对任意类型的数组进行排序。但下面对于某个类的对象的数组排序,需要重载 > 与 < 操作符。
template <class T>
class MyRect {
public:MyRect() :length(0), width(wid) {}MyRect(T len,T wid):length(len),width(wid){}T Area() {return length * width;}
private:T length;T width;
};
//
template <class T>
operator > (MyRect<T>& rect1, MyRect<T>& rect2) {return rect1.Area() > rect2.Area() ? true : false;
}
//
template <class T>
operator < (MyRect<T>& rect1, MyRect<T>& rect2) {return rect1.Area() < rect2.Area() ? true : false;
}
更多推荐
C和C++程序员面试秘笈之⑩
发布评论