5、面向对象的编程风格-C++

一、定义一个抽象基类

如果基类定义有虚成员函数,基类的析构函数一般声明为虚函数(防止子类释放时,父类没有析构,造成内存泄漏)

任何类如果声明有一个(或多个)纯虚函数,那么,由于其接口的不完整性(纯虚函数没有函数定义,是谓不完整),程序无法为它产生任何对象。这种类只能作为派生类的子对象使用,而且前提是这些派生类必须为所有虚函数提供确切的定义。

二、定义一个派生类

如果通过基类的接口无法访问子类特有的接口;如果在基类定义上同名的纯虚函数。这样,子类的同名函数就自动成为虚函数——它们不需要再指定关键字virtual。如果子类的函数再加virtual,那么修改父类的对象就要大费周章:每个子类都必须对它重新声明。

三、基类的抽象

如果类的数据成员是引用类型,必须在构造函数的初始化列表加以初始化。一旦初始化之后,就再也无法指向另一个对象。

四、初始化、析构、复制

当基类有数据成员时,为基类提供构造函数,利用构造函数处理基类所声明的所有数据成员的初始化操作。

一个抽象基类由于无法定义任何对象,其角色是每个子类对象的子对象;因此,我们可以将基类的构造声明为protected。

子类对象的初始化行为,包含调用基类的构造函数,然后再调用自身的构造函数。

子类的构造函数,不仅必须为自身的数据成员进行初始化操作,还要为父类的数据成员提供适当的值。
例如:

inline fib::fib(int len,int pos)
:num_seq(len,pos,elem){
}

拷贝构造时:首先,父类子对象会把逐一初始化,然后子类的成员也会被逐一初始化。

如果我们将某个fib对象赋值给另一个fib对象时,而且fib类拥有明确定义的拷贝赋值操作,它便会再赋值操作时发生调用。以下便是其中一种定义方式,必须明确调用基类的拷贝赋值操作。

fib & fib::operator=(const fib &rhs){
	if(this!=&rhs)
	//明确调用父类的拷贝赋值操作
	num_seq::seq=(rhs);
	return *this;
}

五、在派生类中定义一个虚函数

如果决定覆盖基类的所提供的虚函数,那么派生类提供的新定义,其函数原型必须完全符合基类所声明的函数原,包括参数列表、返回类型、常量性(const-ness)。
一般情况下,派生类提供的函数和基类同名函数没有完全吻合,不能覆盖基类的同名函数。但是有种例外——当基类的虚函数返回某个基类形式(通常是pointer或reference)时:

class num_seq{
public:
	//派生类的clone函数可以返回一个指针 指向num_seq的任何一个派生类
	virtual num_seq *clone()=0;
};

派生类中;的同名函数便可以返回基类所派生出来的类型:

class fib: public num_seq{
public:
	//ok fib乃派生自num_seq
	//在派生类中 virtual并非必要
	fib *clone(){return new fib(*this)}
}

虚函数的静态解析:

有两种情况。虚函数机制不会出现预期行为:(1)基类的构造和析构函数内(2)当我们使用的是基类的对象,而非基类对象的pointer或reference时。

当我们构造派生类对象时,基类的构造函数先被调用,如果此时基类的构造函数调用某个虚函数,一定是其自身的函数,因为此时派生类中的成员函数尚未初始化。

在C++中,唯有用基类的指针和引用才能支持面向对象编程概念。当一个基类声明一个实际对象,但是传入的却是一个派生类对象,属于基类拥有的成员会被保存,基类没有的类型会被切掉。

运行时的类型鉴定机制
typeid运算符,是所谓运行时类型鉴定机制(run time type identification RTTI)的一部分,由程序语言支持。它让我们查询多态的class pointer或class reference,获得其所指对象的实际类型。

#include<typeidfo>
inline const char * num_seq:: what_am_i()const
{	
	return typeid(*this).name();
}

每一个多态类都对应一个typd_info对象。

static_cast

if(typeid(*ps)==typeid(fib)){
	fib * pf=static_cast<fib *>(ps);//无条件转换
	pf->gen_elem(64);
}

static_cast其实有潜在风险,因为编译器无法确认我们所进行的转换操作是否完全正确,这就是 typeid(*ps)==typeid(fib) 使用的原因。

danamic_cast提供有条件的转换,也是RTTI运算符,会进行运行时检验操作,检验ps所指对象是否属于fib类。

if(fib *pf=dynamic_cast<fib *>(ps))
	pf->gen_elem(64);

在这里插入图片描述

答案

#include <iostream>

using namespace std;


#include<iostream>
#include<string>
#include<vector>
using namespace std;
typedef string elemType;

class Stack
{
public:
//    Stack();
    virtual ~Stack(){}
    virtual bool pop(elemType &)=0;
    virtual bool push(const elemType&)=0;
    virtual bool peek(int index,elemType&)=0;

    virtual int top() const =0;
    virtual int size() const =0;

    virtual bool empty() const =0;
    virtual bool full() const =0;
    virtual void print(ostream& =cout ) const=0;
};

ostream& operator<<(ostream &os,const Stack &rhs)
{
    rhs.print();return os;
}

class LIFO_Stack:public Stack{
public:
    LIFO_Stack(int capacity=0):_top(0){
        if(capacity) _stack.reserve(capacity);
    }
    int size() const {return _stack.size();}
    bool empty() const {return !_top;}
    bool full() const {return size()>=_stack.max_size();}
    int top() const{return _top;}
    void print(ostream &os=cout) const;

    bool pop(elemType &elem);
    bool push(const elemType& elem);
    bool peek(int,elemType&){return  false;}


private:
    vector<elemType> _stack;
    int _top;

};

void LIFO_Stack::print(ostream &os) const{
    vector<elemType>::const_reverse_iterator rit=_stack.rbegin(),
    rend=_stack.rend();
    os<<"\n\t";
    while (rit!=rend) {
        os<<*rit++<<"\n\t";
    }
}

bool LIFO_Stack::pop(elemType &elem){
    if(empty()) return false;
    elem=_stack[--_top];
    _stack.pop_back();
    return true;
}
bool LIFO_Stack::push(const elemType& elem){
    if(full()) return false;
    _stack.push_back(elem);
    ++_top;
    return true;
}


class Peekback_Stack:public Stack{
public:
    Peekback_Stack(int capacity=0):_top(0){
        if(capacity) _stack.reserve(capacity);
    }
    int size() const {return _stack.size();}
    bool empty() const {return !_top;}
    bool full() const {return size()>=_stack.max_size();}
    int top() const{return _top;}
    void print(ostream &os=cout) const;

    bool pop(elemType &elem);
    bool push(const elemType& elem);
    bool peek(int,elemType&);


private:
    vector<elemType> _stack;
    int _top;

};

void Peekback_Stack::print(ostream &os) const{
    vector<elemType>::const_reverse_iterator rit=_stack.rbegin(),
    rend=_stack.rend();
    os<<"\n\t";
    while (rit!=rend) {
        os<<*rit++<<"\n\t";
    }
}

bool Peekback_Stack::pop(elemType &elem){
    if(empty()) return false;
    elem=_stack[--_top];
    _stack.pop_back();
    return true;
}
bool Peekback_Stack::push(const elemType& elem){
    if(full()) return false;
    _stack.push_back(elem);
    ++_top;
    return true;
}


bool Peekback_Stack::peek(int index,elemType& elem)
{
    if(empty())
    return  false;
    if(index<0||index>=size())
        return false;
    elem=_stack[index];
    return true;
}
/*
 * 非成员函数peek接受一个“抽象类stack的引用”作为参数,
 * 并在函数内调用该stack对象的虚函数peek
 *
*/
void peek(Stack &st,int index){
    cout<<endl;
    string t;
    if(st.peek(index,t))
        cout<<"peek: "<<t;
    else {
        cout<<"peek failed";
    }
    cout<<endl;
}

int main()
{
    LIFO_Stack st;
    string str;
    while (cin>>str&&!st.full()) {
        st.push(str);
        if(cin.get()=='\n')
         break;
    }

    cout<<'\n'<<"about to call peek() with LIFO_Stack"<<endl;

    peek(st,st.top()-1);
    cout<<st;
    Peekback_Stack pst;
    while (!st.empty()) {
        string t;
        if(st.pop(t))
            pst.push(t);

    }

    cout<<"about to call peek() with Peekback_Stack"<<endl;
    peek(pst,pst.top()-1);
    cout<<pst;
    cout << "Hello World!" << endl;
    return 0;
}

在这里插入图片描述

在这里插入图片描述

#include <iostream>
#include <vector>
using namespace std;
typedef string elemType;
class Stack{
public:
    Stack(int capacity=0):_top(0){
        if(capacity)
            _stack.reserve(capacity);
    }
    virtual ~Stack(){}



    bool pop(elemType &);
    bool push(const elemType& );
    virtual bool peek(int,elemType&)
    {return  false;}

    int size() const {return _stack.size();}
    int top() const{return _top;}
    bool empty() const {return !_top;}
    bool full() const {return size()>=_stack.max_size();}

    void print(ostream &os=cout) const;

private:
    vector<elemType> _stack;
    int _top;

};

class Peekback_Stack: public Stack{
public:
    Peekback_Stack(int capacity=0):Stack(capacity){}

    virtual bool peek(int index,elemType& elem);
};

int main()
{
    cout << "Hello World!" << endl;
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值