C++ primer plus 学习笔记 (第14章)

第14章 C++中的代码重用
包含、私有继承和保护继承用于实现has-a关系,即新的类将包含另一个类的对象。
多重继承使得能够使用两个或更多的基类派生出新的类,将基类的功能组合在一起。
类模板使我们能够使用通用术语定义类,然后使用模板来创建针对待定类型定义的特殊类。

14.1.1 valarray 类简介

14.2 私有继承
实现has-a关系的另一种途径—私有继承。使用私有继承,基类的公有成员和保护成员都将成为派生类的私有成员。

// studenti.h -- defining a Student class using private inheritance
#ifndef STUDENTC_H_
#define STUDENTC_H_
#include <iostream>
#include <valarray>
#include <string>   
class Student : private std::string, private std::valarray<double>
{   
private:
    typedef std::valarray<double> ArrayDb;
    // private method for scores output
    std::ostream & arr_out(std::ostream & os) const;
public:
    Student() : std::string("Null Student"), ArrayDb() {}
    explicit Student(const std::string & s)
            : std::string(s), ArrayDb() {}
    explicit Student(int n) : std::string("Nully"), ArrayDb(n) {}
    Student(const std::string & s, int n)
            : std::string(s), ArrayDb(n) {}
    Student(const std::string & s, const ArrayDb & a)
            : std::string(s), ArrayDb(a) {}
    Student(const char * str, const double * pd, int n)
            : std::string(str), ArrayDb(pd, n) {}
    ~Student() {}
    double Average() const;
    double & operator[](int i);
    double operator[](int i) const;
    const std::string & Name() const;
// friends
    // input
    friend std::istream & operator>>(std::istream & is,
                                     Student & stu);  // 1 word
    friend std::istream & getline(std::istream & is,
                                  Student & stu);     // 1 line
    // output
    friend std::ostream & operator<<(std::ostream & os,
                                     const Student & stu);
};
#endif

2)访问基类的方法
使用私有继承时,只能在派生类的方法中使用基类的方法。(在使用包含时将使用对象名来调用方法,而使用私有继承时将使用类名和作用域解析运算符来调用方法。)

14.2.3 保护继承
保护继承在列出基类时使用关键字protected:

14.3 多重继承(MI)
MI描述的是有多个直接基类的类。公有MI表示的也是is-a关系:

class  SingingWaiter:public Waiter,public Singer{...};

注意,必须使用关键字public来限定每一个基类。如果缺省关键字,编译器将认为是私有派生。

14.3.1
C++引入多重继承的同时,引入了一种新技术----虚基类(virtual base class),使MI成为可能。

  1. 虚基类
    虚基类使得从多个类(它们的基类相同)派生出的对象只继承一个基类对象。
    例如,通过在类声明中使用关键字virtual,可以使worker被用作singer和waiter的虚基类(virtual和public的次序无关紧要):
class singer:virtual public worker{...};
class waiter:public virtual worker {...};

然后,可以将singingwaiter定义为:

class singingwaiter:public singer,public waiter {...};
  1. 新的构造函数规则
    使用虚基类时,需要对类构造函数采用新的方法。对于非虚基类,唯一可以出现在初始化列表中的构造函数是即时基类构造函数。显式基类构造函数可为:
singingwaiter(const worker & wk,int p=0,int v=singer::other):worker(wk),waiter(wk,p),singer(wk,v){}

对于虚基类,显式地调用构造函数worker(const worker &)是合法的,但对于非虚基类,则是非法的。
在祖先相同时,使用MI必须引入虚基类,并修改构造函数初始化列表的规则。

14.4 类模板
C++的类模板为生成通用的类声明提供了一种更好的方法。
模板提供参数化类型,即能够将类型名作为参数传递给接收方来建立类或函数。

14.4.1 定义类模板
可以将所有的模板信息放在一个头文件中,并在使用这些模板的文件中包含该头文件。

// 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 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>
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

由上述头文件定义可以知道,模板类以下面这样的代码开头:

template <class Type>

14.4.2 使用模板类

stack<int> kernels;
stack<string> colonels;

猜你喜欢

转载自blog.csdn.net/qq_24251645/article/details/86532602