目录
一、题目
重写下面的类定义,使它成为一个类模板:
class example1{
public:
example1(double min, double max);
example1(const double *array, ine size);
double& operator[](int index);
bool operator==(const example1&)const;
bool insert(const double*,int);
bool insert(double);
double min() const {return _min;};
double max() const {return _max;};
void min(double);
void max(double);
int count(double value) const;
private:
int size;
double *parray;
double _min;
double _max;
}
二、解答
template <class T>
class example1 {
public:
example1(T min, T max);
example1(const T* array, int size);
T& operator[](int index);
bool operator==(const example1<T>&) const;
bool insert(const T* array, int size);
bool insert(T value);
T min() const { return _min; };
T max() const { return _max; };
void min(T value);
void max(T value);
int count(T value) const;
private:
int size;
T* parray;
T _min;
T _max;
};
template <class T>
example1<T>::example1(T min, T max) : size(0), parray(nullptr), _min(min), _max(max) {}
template <class T>
example1<T>::example1(const T* array, int size) : size(size), _min(0), _max(0) {
parray = new T[size];
for (int i = 0; i < size; i++) {
parray[i] = array[i];
if (i == 0 || _min > array[i]) {
_min = array[i];
}
if (i == 0 || _max < array[i]) {
_max = array[i];
}
}
}
template <class T>
T& example1<T>::operator[](int index) {
return parray[index];
}
template <class T>
bool example1<T>::operator==(const example1<T>& other) const {
if (size != other.size) {
return false;
}
for (int i = 0; i < size; i++) {
if (parray[i] != other.parray[i]) {
return false;
}
}
return true;
}
template <class T>
bool example1<T>::insert(const T* array, int size) {
if (array == nullptr || size <= 0) {
return false;
}
T* new_array = new T[this->size + size];
for (int i = 0; i < this->size; i++) {
new_array[i] = parray[i];
}
for (int i = 0; i < size; i++) {
new_array[this->size + i] = array[i];
if (i == 0 || _min > array[i]) {
_min = array[i];
}
if (i == 0 || _max < array[i]) {
_max = array[i];
}
}
delete[] parray;
parray = new_array;
this->size += size;
return true;
}
template <class T>
bool example1<T>::insert(T value) {
return insert(&value, 1);
}
template <class T>
void example1<T>::min(T value) {
_min = value;
}
template <class T>
void example1<T>::max(T value) {
_max = value;
}
template <class T>
int example1<T>::count(T value) const {
int cnt = 0;
for (int i = 0; i < size; i++) {
if (parray[i] == value) {
cnt++;
}
}
return cnt;
}
在上面的示例中,我们使用了类模板的定义方式,并在类的各个成员函数中使用了类型参数T来代。
三、C++类模板的概念
C++类模板是一种通用的类定义,它能够定义一个通用的类模板,并根据模板参数的不同生成具有不同数据类型的类。模板参数是一个或多个占位符,这些占位符在模板实例化时被替换成具体的类型或值。
类模板的定义使用关键字template
,后面跟着尖括号<>
,其中包含一个或多个模板参数。
四、C++类模板的优点
-
代码重用:类模板允许我们编写通用的代码,可以适用于多种类型。通过使用类模板,我们可以避免为每种数据类型编写重复的代码,从而提高代码的可重用性。
-
类型安全:类模板是类型安全的,因为它们要求在编译时指定类型参数。这样可以避免在运行时出现类型错误。
-
灵活性:类模板可以与其他C++特性(如继承、多态和模板特化)一起使用,从而提高了编程灵活性。
-
性能优化:通过使用类模板,可以提高程序的执行效率,因为编译器可以对模板进行优化。特别是在容器类等需要频繁访问元素的情况下,使用模板可以大幅提高程序的性能。
五、C++类模板的应用场景
C++类模板的应用场景非常广泛,主要体现在以下几个方面:
-
容器类:STL中的容器类如
vector
、list
、map
等都是基于类模板实现的。容器类需要存储不同类型的数据,因此使用类模板可以很方便地实现通用的容器类,避免了重复编写代码的问题。 -
泛型算法:STL中的算法如
sort
、find
、count
等也是基于类模板实现的。这些算法需要适用于不同类型的数据,因此使用类模板可以很方便地实现通用的算法。 -
模板元编程:模板元编程是一种在编译期进行计算的技术,它利用类模板和模板特化实现了一些高级编程技巧,如类型推导、编译期计算、元编程等。
-
泛型编程:泛型编程是一种以通用性为目的的编程方法,它利用类模板和函数模板实现通用代码,适用于不同类型的数据。通过使用泛型编程,可以提高代码的可重用性和灵活性。
六、使用C++类模板时的注意事项
使用C++类模板时需要注意以下几点:
-
类模板的定义和实现通常需要放在头文件中,因为编译器需要在使用类模板的地方实例化出具体的类。因此,如果将类模板的定义和实现放在不同的文件中,可能会导致编译错误。
-
类模板中的成员函数通常也需要在类模板定义的头文件中实现,而不是在cpp文件中。这是因为,当其他文件调用类模板中的成员函数时,编译器需要能够访问到这些函数的定义。
-
在使用类模板时,必须在尖括号中指定类型参数。如果类型参数不正确或缺少类型参数,编译器将无法实例化出具体的类。
-
类模板中可能包含一些非类型参数(如int、double等),这些参数在实例化时需要被指定。需要注意的是,这些非类型参数的取值通常需要满足一定的限制,否则会导致编译错误。
-
类模板可以特化,即可以为特定的类型提供特定的实现。需要注意的是,类模板特化的语法和模板实例化的语法很相似,容易混淆。
C++类模板是一种非常强大的工具,可以用于实现通用的代码,避免了重复编写代码的问题,提高了代码的可重用性和灵活性。在C++中,类模板已经成为一种常见的编程技巧,得到了广泛应用。