第十六章 16.1.2节练习

练习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
};
把类声明部分改了一下,其他实现部分就不在往上加了。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值