第14章——C++的代码重用

来源:互联网 发布:抓包软件有哪几种 编辑:程序博客网 时间:2024/06/05 11:07
 

C++的一个主要目标是促进代码重用。公有继承是实现这种目标的机制之一,但并不是惟一的机制。还有包含,私有继承和保护继承。通常他们是用来实现has-a关系。

l         包含对象的类

就是类的成员本身又是另外一个类的对象。

eg:

class student

{

       private:

              string name;

              valarray<double> scores;

              ……

};

student类获得了其成员对象的实现,但没有继承其接口。即student类中的string类和valarray<double>类的方法可以在student类方法实现中使用,但在student外部,不能使用string类和valarray<double>类的方法。

对其构造函数的实现:

student(const char *str,const double *pd,int n)

       :name(str),scores(pd,n){}

 构造函数初始化的是成员对象,而不是继承的对象,所以在初始化列表中使用的是成员名,而不是类名。

对于继承的对象,构造函数在成员初始化列表中使用类名来调用特定的基类构造函数。对于成员对象,构造函数使用成员名。

l         私有继承

使用私有继承,基类的公有成员和保护成员都将为派生类的私有成员。这意味着基类方法将不会成为派生对象公有接口的一部分,但可以在派生类的成员函数中使用它们。

eg:

class student:private  std::string,private std::valarray<double>

{

       public:

       …

};

要执行私有继承,请使用关键字private。实际上,private是默认值,因此省略访问限定符也将导致私有继承。

私有继承的构造函数

student(const char *str,const double *pd,int n)

       :std::string(str),ArrayDb(pd,n){}

使用包含时将使用对象名来调用方法,而使用私有继承时将使用类名和作用哉解析操作符来调用。

 

使用保护继承时,基类的公有成员和保护成员都将成为派生类的保护成员。使用私有继承时,第三代类将不能使用基类的接口,而保护继承时,第三代类可以使用。

在保护派生或私有派生时,要让基类的方法在派生类外面可用,有两种方法

1.       定义一个使用该基类方法的派生类方法

2.       使用一个using声明

eg:

class student:private std:string,private std::valarray<double>

{

public:

        using std::valarray<double>::min;

        using std::valarray<double>::max;

        …

};

using声明只适用于继承,而不适用于包含。

l         多重继承

MI描述的是有多个直接基类的类。

MI可能给程序员带来两个主要的问题:1.从两个不同的基类继承同名方法 2.从两个或更多相关基类那里继承同一个类的多个实例。

类限定符可以解决名称二义性问题,引用虚基类来避免继承多个基类对象的问题。

cass singer:virtual public worker{…};

cass waiter:virtual public worker{…};

class singingwaiter:public singer,public waiter{…};

worker被用作singer和waiter的虚基类。singingwaiter对象将只包含worker对象的一个拷贝。

MI的构造函数

singingwaiter(const worker &wk,int p=0,int v= singer::other)

              :worker(wk),waiter(wk,p),singer(wk,v){}

上述代码显式调用构造函数 worker(const worker &)。对于虚基类,必须这样做,对于非虚基类,则是非法的。

l         类模板

模板,接受的参数是类型。

类模板和函数模板开头都有template <class Type>或template <typename Type>

类模板就是前面的声明,再加上类中被Type取代的具体类型。因为模板不是函数,它们必须与特定的模板实例化请求一起保用。

eg:

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 item

public:

    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>,而且方法名前加限定符

eg:

template <class Type>

Stack<Type>::Stack()

{

    top = 0;

}

 

指针也可以是用作模板处理的类型。模板可以有多个参数,参数可以是类型参数,也可以是非类型参数。类模板中可以给类型参数和非类型参数提供默认值,函数模板只能给非类型参数提供默认值。

 

模板可以被显式实例化

template class ArrayTP<string,100>

模板具体化

template <> class sortedarray<char *>{…};

 

模板可用作结构、类或模板类的成员。

模板用作参数

template <template <typename T> class Thing>

class crab

{

       private:

              Thing<int> s1;

              Thing<double> s2;

……

};

模板参数是template <typename T> class。这意味着s1是一个类,这个类用template <typename T>这个模板进行隐式实例化。T为int.

 

模板类和友元

非模板友元

 template <class T>

class HasFriend

{

       friend void counts();

       friend void report(HasFriend<T> &);

       …

};

以上类中counts()和reports()函数并不是模板函数,当模板当实例成doulbe和int类型时,

counts()和reports()的定义

void counts()

{

       cout<<”int count: ”<<HasFriend<int>::ct<<”;”;

       cout<<”double count: ”<<HasFriend<double>::ct<<”;”;

}

 

void reports(HasFriend<int> &hf)

{

       cout<<” HasFriend<int>: ”<<hf.item<<endl;

}

 

void reports(HasFriend<double> &hf)

{

       cout<<” HasFriend<double>: ”<<hf.item<<endl;

}

 

模板类的约束模板友元函数

包含3步:

1.       template <typename T> void counts();

template <typename T> void reports(T &);

2.       在类中声明

template <typename TT>

class HasFriend

{

       friend void counts<TT>();

       friend void report<>(HasFriend<T> &);

       …

};

 

counts()函数没有参数,所以必须显式具体化。所以在friend前可有template<>

reports()后<>为空,因为它有参数,可被它有函数参数来确定模板类型参数。

 

3.模板定义

非约束模板友元函数

通过在类内部声明模板,可以创建非约束码元函数

 template <typename T>

class ManyFriend

{

       template <typename C,typename D> friend void show2(C&,D&);

       …

};

调用:

ManyFriend<int> hfi1(10);

ManyFriend<int> hfi2(20);

show2(hfi1,hfi2);

原创粉丝点击