练习16.9
什么是函数模板?什么是类模板?
解答:
【引用】函数模板就是一个公式,可用来生成针对特定类型的函数版本
【引用】类模板是用来生成类的蓝图。与函数模板的不同之处是,编译器不能为类模板推断模板参数类型。
练习16.10
当一个类被实例化时,会发生什么?
解答:
【引用】这里需要显式模板实参列表,他们被绑定到模板参数。编译器使用这些末班实参来实例化出特定的类。
练习16.11
下面List的定义是错误的。应如何修正它?
template <typename elemType> class ListItem;
template <typename elemType> class List{
public:
List<elemType>();
List<elemType>(const List<elemType> &);
List<elemType>& operator=(const List<elemType> &);
~List();
void insert(ListItem *ptr, elemType value);
private:
ListItem *front, *end;
};
解答:
多谢 隔壁的程序 同学的勘误。
对原题中给出的代码,看下clang3.4会抱怨什么。命令:clang++ -c -std=c++11 test.cc
test.cc:9:15: error: use of class template 'ListItem' requires template arguments
void insert(ListItem *ptr, elemType value);
^
test.cc:1:36: note: template is declared here
template <typename elemType> class ListItem;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
test.cc:11:3: error: use of class template 'ListItem' requires template arguments
ListItem *front, *end;
^
test.cc:1:36: note: template is declared here
template <typename elemType> class ListItem;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
2 errors generated.
错误提示中很明确的说了,模板需要模板参数。
所以,这里与友元操作没有太大关系。
修正后的代码如下:
template <typename elemType> class ListItem;
template <typename elemType> class List{
public:
List<elemType>();
List<elemType>(const List<elemType> &);
List<elemType>& operator=(const List<elemType> &);
~List();
void insert(ListItem<elemType> *ptr, elemType value);
private:
ListItem<elemType> *front, *end;
};
练习16.12
编写你自己版本的Blob和BlobPtr模板,包含书中未定义的多个const成员。
解答:
这里其实就是给书中的两个模板类进行函数实现的填充,这里注意一下模板函数的实现即可。
实现可以参考之前章节的内容。
练习16.13
解释你为BlobPtr的相等和关系运算符选择哪种类型的友好关系?
解答:
operator==<T>(const BlobPtr<T>&, const BlobPtr<T>&);
这里需要与类型一一对应,所以就选择和实例化时类型一致的类型。
练习16.14
编写Screen类模板,用非类型参数定义Screen的高和宽。
练习16.15
为你的Screen模板实现输入和输出运算符。Screen类需要哪些友元(如果需要的话)来令输入和输出运算符正常工作?解释每个友元声明(如果有的话)为什么是必要的。
解答:
这还稍稍有些困难,模板函数的输入输出操作符还和普通类的定义方式有些不同。
参考博文:http://www.cnblogs.com/xkfz007/articles/2534322.html
#include <iostream>
#define WAY 1
template <typename T>
struct Screen{
#if WAY == 1
friend std::istream &operator>>(std::istream &in, Screen<T>& screen){
in >> screen.height >> screen.length;
if (!in){
screen = Screen();
}
return in;
}
friend std::ostream &operator<<(std::ostream &out, const Screen<T> &screen){
out << "height: " << screen.height << " length: " << screen.length;
return out;
}
#endif
Screen() = default;
T height;
T length;
};
#if WAY == 2
template <typename T>
std::ostream &operator<<(std::ostream &out, const Screen<T> &screen){
out << "height: " << screen.height << " length: " << screen.length;
return out;
}
template <typename T>
std::istream &operator>>(std::istream &in, Screen<T>& screen){
in >> screen.height >> screen.length;
if (!in){
screen = Screen<T>();
}
return in;
}
#endif
typedef Screen<double> dScreen;
typedef Screen<std::size_t> iScreen;
int main(){
dScreen dtest;
std::cin >> dtest;
std::cout << dtest << std::endl;
iScreen itest;
std::cin >> itest;
std::cout <<itest << std::endl;
}
我使用了上面博文中的两种方法,分别用宏隔开。
练习16.16
将StrVec类(参见13.5节,第465页)重写为模板,命名为Vec。
解答:
template <typename>
class Vec {
public:
// copy control members
Vec():elements(nullptr), first_free(nullptr), cap(nullptr) { }
Vec(const Vec<T>&); // copy constructor
Vec &operator=(const Vec<T>&); // copy assignment
Vec(Vec<T>&&) noexcept; // move constructor
Vec &operator=(StrVec<T>&&) noexcept; // move assignment
~Vec() noexcept; // destructor
// additional constructor
Vec(std::initializer_list<T>);
void push_back(const T&); // copy the element
void push_back(T&&); // move the element
// add elements
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
// iterator interface
T *begin() const { return elements; }
T *end() const { return first_free; }
// operator functions covered in chapter 14
Vec &operator=(std::initializer_list<T>);
T& operator[](std::size_t n)
{ return elements[n]; }
const T& operator[](std::size_t n) const
{ return elements[n]; }
// emplace member covered in chapter 16
template <class... Args> void emplace_back(Args&&...);
private:
static std::allocator<T> alloc; // allocates the elements
// utility functions:
// used by members that add elements to the StrVec
void chk_n_alloc()
{ if (size() == capacity()) reallocate(); }
// used by the copy constructor, assignment operator, and destructor
std::pair<T*, T*> alloc_n_copy(const T*, const T*);
void free(); // destroy the elements and free the space
void reallocate(); // get more space and copy the existing elements
T *elements; // pointer to the first element in the array
T *first_free; // pointer to the first free element in the array
T *cap; // pointer to one past the end of the array
};
把类声明部分改了一下,其他实现部分就不在往上加了。