《C++ primer plus》第十四章:C++的代码重用 学习笔记

来源:互联网 发布:武汉最新网络约车新规 编辑:程序博客网 时间:2024/05/21 12:49

《C++ primer plus》第十四章:C++的代码重用 学习笔记

这一章主要讲述了C++中的模板问题

1.valarray类的使用

valarray<int> v1;int gpa[4] = {1,2,3,4};valarray<int> v2; //sizeo 0valarray<int> v2(10); //size 10;valarray<int> v3(10,8);//size 8,each set to 10valarray<int> v4(gpa,4);//copy//valarray的一些函数sum, size, max, min, operator[];


2.成员初始化语法
一般来说,const数据成员必须用初始化语法,而非const不要求,但也可用


3.私有继承
派生类通过使用基类名和作用域解释操作符可以调用基类的方法
使用私有继承时,基类的公有成员和保护成员都变成了派生类的私有成员
使用派生继承时,基类的公有成员和保护成员都变成了派生类的保护成员



4.使用using重新定义访问权限
使用保护派生或私有派生时,如果想要在类外使用基类的方法:
一种方法是定义一个使用该基类方法的派生类方法
另一种方法是将函数调用包装在另一个函数的调用里,使用using声明,这样即使是私有声明也可以使用
(注意:第二种方法using声明只使用成员名,没有括号,函数特征表和返回值)



5.多重继承(MI)
(1)为了使从多个类派生出来的对象只有一个基类,使用虚基类,在类声明中使用virtual

class Singer:virtual public Worker{};class Waiter:virtual public Worker{};

使用虚基类时,C++禁止信息通过中间类自动传递给基类,因此,虚基类的构造函数应该是这样的:

SingWaiter(const Worker&a,int p,int v):Worker(a),Waiter(a,p),Singer(a,v){}

注意:这种做法对于非虚基类是不合法的


(2)MI可能造成函数的二义性,因此可以通过函数作用域解释操作符来确定那个函数,但是更好的方法是在派生类中
进行重定义,并指出要使用那个版本


6.类模板
(1)使用模板成员函数代替原有类的方法时,每个函数头都将以相同的模板声明开头:template <typename T>
同时,还需将Stack:: 改为Stack<Type>::
(2)模板不是函数,不能单独编译,必须与特定的模板实例化请求一起使用


7.深入讨论类模板
(1)正确使用指针堆栈
(2)递归使用类模板建立二维至多维数组

ArrayTP<int, 10> sums;//int[10]ArrayTP<double, 10> aves;//double[10]ArrayTP< ArrayTP<int,5>, 10> twodee;//int[10][5]


(3)使用多个类型参数

#include <iostream>#ifndef PAIR_H#define PAIR_Htemplate <typename T1,typename T2>class Pair{public:Pair(){}//~Pair();Pair(const T1& a1,const T2& b1){a = a1;b = b1;}T1 getfir()const{return a;}T2 getsec()const{return b;}private:T1 a;T2 b;};#endifusing namespace std;int main(){Pair<string,int> test("Max",12);cout << test.getfir() << ": " << test.getsec() << endl;}


(4)默认模板参数

template <typename T1,typename T2 = int> class Topo{};Topo<double,double> m1;//T1 is double,T2 is doubleTopo<double> m2;//T1 is double,T2 is int


(5)模板具体化

<1>隐式实例化

<2>显式实例化

<3>显式具体化:用特定类型替换模板中的通用类型

例如,但模板使用>操作符进行比较时,对于数字,也许管用,但是对于字符串,就需要显示具体化。

template<> class Array(char *){......}

<4>部分具体化:给类型参数之一指定具体的类型

//general templatetemplate<class T1,class T2>class Pair{};//部分具体化template<class T1>class Pair{};

或者通过为指针提供特殊版本来部分具体化现有的模板

template<class T*>
//如果类型不是指针,函数将使用通用版本,如果提供的是指针,则编译器将使用指针具体化版本

(6)成员模板:模板可用做结构、类或模板类的成员

#include <iostream>using namespace std;template <typename T>class first{public:first(T t,int i):q(t),n(i){}//~first();void show()const{q.show();n.show();}private:template <typename U>class hold{public:hold(U u = 0){val = u;}//~hold();void show()const{cout << val << endl;}U getval()const{return val;}private:U val;};hold<T> q;hold<int> n;};int main(){first<double> guy(3.5,12);guy.show();return 0;}

(7)将模板用作参数

// stacktp.h -- a stack template#ifndef STACKTP_H_#define STACKTP_H_template <class Type>class Stack{private:    enum {MAX = 10};    // constant specific to class    Type items[MAX];    // holds stack items    int top;            // index for top stack itempublic:    Stack();    bool isempty();    bool isfull();    bool push(const Type & item); // add item to stack    bool pop(Type & item);        // pop top into item};template <class Type>Stack<Type>::Stack(){    top = 0;}template <class Type>bool Stack<Type>::isempty(){    return top == 0;}template <class Type>bool Stack<Type>::isfull(){    return top == MAX;}template <class Type>bool Stack<Type>::push(const Type & item){    if (top < MAX)    {        items[top++] = item;        return true;    }    else        return false;}template <class Type>bool Stack<Type>::pop(Type & item){    if (top > 0)    {        item = items[--top];        return true;    }    else        return false; }#endif

(8)模板类和友元
<1>模板类的非模板友元函数

template <class T>class Hasfriend{friend void counts();};//访问模板类参数时,必须指明具体化template <class T>class Hasfriend{friend void report(Hasfriend<T>&);//指明具体化};

#include <iostream>using namespace std;template <typename T>class Hasfriend{friend void show();friend void report(Hasfriend<T>& a);public:Hasfriend(const T& a):items(a){count++;}~Hasfriend(){count--;}private:T items;static int count;};template <typename T>int Hasfriend<T>::count = 0;void show(){cout << "Hasfriend<int> count: " << Hasfriend<int>::count << endl;cout << "Hasfriend<double> count: " << Hasfriend<double>::count << endl;}void report(Hasfriend<int>& a){cout << "Hasfriend<int> items: " << a.items << endl;}void report(Hasfriend<double> &a){cout << "Hasfriend<double> items: " << a.items << endl;}int main(){Hasfriend<int> a(12);Hasfriend<double> b(12.2);show();report(a);report(b);return 0;}

<2>模板类的约束模板的友元函数

修改前一个范例,是友元函数本身成为模板,分3步
A.在类定义前面声明每一个模板函数

template<typename T>void counts();template<typename T>void report(T &);

B.在函数中再次将模板声明为友元

template<typename TT>class Hasfriend{friend void counts<TT>();//对于report,<>可以为空,因为可以从函数参数中推断出模板的参数类型friend void report<>(Hasfriend<TT> &);};

C.为友元提供模板定义

template <typename T>void counts(){...}template<typename T>void report(T &hf){...}

//模板类的约束模板的友元函数
#include <iostream>using namespace std;template <typename T> void show();template <typename T> void report(T &a);template <typename T>class Hasfriend{public:Hasfriend(const T&a):items(a){count++;}~Hasfriend(){count--;}friend void show<T>();friend void report<>(Hasfriend<T>& a);private:T items;static int count;};template <typename T>int Hasfriend<T>::count = 0;template <typename T>void show(){cout << "Hasfriend count: " << Hasfriend<T>::count << endl;}template <typename T>void report(T& a){cout << a.items << endl;}int main(){Hasfriend<int> a(12);Hasfriend<int> b(13);Hasfriend<double> c(12.2);show<int>();show<double>();report(a);report(b);report(c);return 0;}


<3>模板类非约束模板的友元函数

template<typename T>class Manyfriend{template<typename T1,typename T2> friend void show2(T1 &,T2 &)};

//模板类非约束模板的友元函数
#include <iostream>using namespace std;template <typename T>class Hasfriend{public:Hasfriend(const T& i):items(i){}//~Hasfriend();template<typename T1,typename T2>friend void show(T1& a,T2& b);private:T items;};template<typename T1,typename T2>void show(T1& a,T2 &b){cout << a.items << " " << b.items << endl;}int main(){Hasfriend<int> a(12);Hasfriend<double> b(12.2);show(a,b);return 0;}







0 0
原创粉丝点击