9、抽象基类num_sequence的创建及使用

num_sequence.h

#include <iostream>
#include <vector>

using namespace std;

class num_sequence
{
    public:
        virtual ~num_sequence(){};                          // 后面加分号

        virtual int         elem( int pos ) const = 0;
        virtual const char *what_am_i() const = 0;
        static int          max_elems() { return _max_elems; }       // 括号后面不加分号
        virtual ostream&    print( ostream &os = cout ) const = 0;      ///////////
     
        //virtual const char*         test(){ return "num_seq test"; }
    protected:
        virtual void        gen_elems( int pos ) const = 0;
        bool                check_integrity( int pos, int size) const;

        const static int    _max_elems = 1024;                 // 前面加 const
};

class Fibonacci : public num_sequence
{
    public:
        Fibonacci( int len = 1, int beg = 1 ) 
            : _len( len ), _beg_pos( beg ){} 

        int                 elem( int pos) const;
        virtual const char  *what_am_i() const { return "Fibonacci"; }
        ostream&            print( ostream &os = cout ) const;

        int                 length(){ return _len; }
        int                 beg_pos(){ return _beg_pos; }

        //const char*         test(){ return "fib_seq test"; }
    protected:
        void                gen_elems( int pos ) const;

    private:
        int                 _len;
        int                 _beg_pos;
        static vector<int>  _elems;

};      // 类后面要加分号

//vector<int> Fibonacci::_elems;  // 在此处定义_elems
//也可以,或者在main.cc,不然会报_elems 未定义错误

// operator<<
ostream& operator<<( ostream &os, const num_sequence &ns)
{
    return ns.print(os);
}

// check_integrity //此处的check_integrity 只是大致判断了范围,不具体不确切
#if 0
inline bool num_sequence::check_integrity ( int pos ) const
{
    if (pos <= 0 || pos > _max_elems)
    {
        cerr << "invailed position" << pos <<endl;
        return false;
    }
    return true;
}
#endif
#if 0
// 更具体的 检查完整性方式,但不完美,check_integrity在基类中并不是virtual
// 因此通过指向基类的指针或引用时会出现只调用基类的check_integrity
// 若采取在基类中定义该函数为virtual,同样也是不完美的,因为根据不完整信息所实现的内容,
// 可能也是不完整的,这和型别相依相悖
inline bool Fibonacci::
check_integrity ( int pos ) const
{
    if (! num_sequence::check_integrity(pos))  //必须加上类运算符,不然就是Fib
        return false;

    if (pos > _elems.size())
        Fibonacci::gen_elems(pos);

    return true;
}
#else
// 因此重写 check_integrity,属于 num_sequence类,
// 采取两个参数
inline bool num_sequence::
check_integrity(int pos, int size) const
{
    if (pos <= 0 || pos > _max_elems)
    {
        cerr << "invailed position" << pos <<endl;
        return false;
    }
    if (pos > size)
        gen_elems(pos);  // 通过虚拟机制调用,结合了gen,因此print 和 elem函数就可以去掉 gen_elems

    return true;
}
#endif

#if 1
//ostream& Fibonacci::print( ostream &os = cout ) const   //此处错误
ostream& Fibonacci::
print( ostream &os) const
{
    unsigned int elem_pos = _beg_pos - 1;  //_beg_pos = 1 initialize
    unsigned int end_pos = elem_pos + _len;

    if (end_pos > _elems.size())
        Fibonacci::gen_elems(end_pos);  // 此处加::作用域 编译期而不用等到执行期
    while (elem_pos < end_pos)
        os << _elems[elem_pos++] << ' ';

    return os;
}
#else
ostream& Fibonacci::
print( ostream &os) const
{
    unsigned int elem_pos = _beg_pos - 1;  //_beg_pos = 1 initialize
    unsigned int end_pos = elem_pos + _len;
    
    if (!check_integrity(end_pos, _elems.size()))
        // 此处不知道返回什么
    while (elem_pos < end_pos)
        os << _elems[elem_pos++] << ' ';

    return os;
}
#endif

#if 0
int Fibonacci::elem( int pos ) const
{
    if ( !check_integrity(pos) )
        return 0;
    if ( (unsigned int)pos > _elems.size())  // 放到了 check_integrity中,相当于每个派生类都不用再写这段添加代码
    {
        Fibonacci::gen_elems(pos);
    }
    return _elems[pos - 1];
}
#else
int Fibonacci::elem( int pos ) const
{
    if ( !check_integrity(pos, _elems.size()) )
        return 0;

    return _elems[pos - 1];
}
#endif

void Fibonacci::gen_elems( int pos ) const
{
    if ( _elems.empty() )
    {
        _elems.push_back(1);
        _elems.push_back(1);
    }
    if ( _elems.size() <= (unsigned int)pos )
    {
        int ix = _elems.size();
        int n_2 = _elems[ix - 2];
        int n_1 = _elems[ix - 1];

        for ( ; ix <= pos; ++ix )
        {
            int elem = n_2 + n_1;
            _elems.push_back(elem);
            n_2 = n_1; n_1 = elem;
        }
    }
}

main.cc

#include "num_sequence.h"



vector<int> Fibonacci::_elems;



int main()
{
    //num_sequence *ps = new Fibonacci;  // 派生类定义了该虚拟函数,才可以定义基类对象,通过派生类定义
    //num_sequence *ps2 = new Fibonacci( 2, 2);
    
    cout << "init main.\n";
    
    Fibonacci fib;
    cout << "fib: beginning at element 1 for 1 element: "
         << fib << endl;    // fib 由于重载了 operator<< 运算发,并且调用print函数

    Fibonacci fib2(10);
    cout << "fib: beginning at element 1 for 10 element: "
         << fib2 << endl;    // fib 由于重载了 operator<< 运算发,并且调用print函数

    Fibonacci fib3(3, 8);  // len = 3, _beg_pos = 7
    cout << "fib: beginning at element 7 for 3 element: "
         << fib3 << endl;    // fib 由于重载了 operator<< 运算发,并且调用print函数
    return 0;
}

猜你喜欢

转载自blog.csdn.net/centnetHY/article/details/88146725