C和C++程序员面试秘笈之⑩

编程入门 行业动态 更新时间:2024-10-26 01:33:31

C和C++<a href=https://www.elefans.com/category/jswz/34/1770040.html style=程序员面试秘笈之⑩"/>

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 &lt; T Y P E L I S T , A R G L I S T &gt; F u n c t i o n D e f i n i t i o n template&lt;TYPE_{LIST},ARG_{LIST}&gt;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;}}}}
};
  1. Sort 成员为 static,可用 Test::Sort 访问;
  2. 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++程序员面试秘笈之⑩

本文发布于:2024-03-09 14:14:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1725203.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:程序员   秘笈

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!