面向对象程序设计第一次实验课——位运算封装

题目的大意是用一个类封装位运算,并通过位运算实现四则运算。我一下子就想起了bitset,但是bitset并不支持四则运算。后来想想也许叫大整数类比较合适吧。

当然还是有很多问题的,有些问题是写完了才发现的,当时发着高烧,一边写一边debug,好不容易赶到deadline前,交过之后也没有改的动力了……

首先是该用友元实现的二元关系的运算符全写在类内了,写之前应该看看书的。其次是没有实现下标运算符的重载,这个要用到设计模式中的代理模式,同样是没来得及写,这里有篇blog里面实现了:
http://blog.csdn.net/fastsort/article/details/8922923

一些其他问题写在了实验报告中。

bit.h

#pragma once
#include <string>
#include <cstring>
#include <cmath>
#define BLOCK (len_ / (8 * sizeof(size_t)) + (len_ % (sizeof(size_t) * 8)? 1: 0))
#define BLOCKBIT (8 * sizeof(size_t)) 
using namespace std;
template <size_t len_> //len_ is the number of bit(s) 
class myBitset {
    friend ostream& operator<< (ostream &out, const myBitset<len_>& bs) 
    {
        // stored reversely, so output reversely
        for (size_t i = 0; i < len_; i ++) {
            if (bs.isTrue(len_ - i - 1)) out << "1";
            else out << "0";
//          printf("%d ",i);
        }
        return out;
    }
    public:
        myBitset() : block_(BLOCK) 
        {
            num_ = new size_t[block_];  
            memset(num_, 0, block_ * sizeof(size_t));
//          printf("%d %d %d\n", block_, sizeof(size_t), block_ * sizeof(size_t));
//          for (int i = 0; i < block_; i ++) num_[i] = 0;
//          cout << *this << endl;      
        }

        myBitset(const myBitset& bs);
//invert signed number to myBitset, and avoid ambiguous calling for overloaded functions
        myBitset(signed int num);
        myBitset(unsigned int num);
        myBitset(signed long);
        myBitset(unsigned long);
//      myBitset(signed long long);
//      myBitset(unsigned long long);
        myBitset(signed __int64 num);
        myBitset(unsigned __int64 num);
        myBitset(const string& s);
        ~myBitset();

        myBitset& operator= (const myBitset& bs);
        myBitset operator& (const myBitset& bs) const; 
        myBitset operator| (const myBitset& bs) const;
        myBitset operator~ (void) const;
        myBitset operator^ (const myBitset& bs) const;
    //  BOTH TWO BELOW ARE LOGICAL SHIFT! BE CAREFUL !
        myBitset operator<< (size_t shift) const;
        myBitset operator>> (size_t shift) const;
        myBitset& operator&= (const myBitset& bs);
        myBitset& operator|= (const myBitset& bs);
        myBitset& operator^= (const myBitset& bs);
        myBitset& operator<<= (size_t shift);
        myBitset& operator>>= (size_t shift);

        myBitset& operator++ (void);
        myBitset& operator-- (void);
        myBitset operator++ (int dummy);
        myBitset operator-- (int dummy);
    //  in operator+= we need local variables of myBitset, so argument is not reference
        myBitset& operator+= (myBitset bs);
        myBitset& operator-= (const myBitset& bs);
        myBitset operator+ (const myBitset& bs) const;
        myBitset operator- (const myBitset& bs) const;
        myBitset operator+ (void) const;
        myBitset operator- (void) const;

        myBitset operator* (const myBitset& bs) const;
        myBitset operator/ (const myBitset& bs) const;
//      myBitset operator% (const myBitset& bs) const;
        myBitset& operator*= (myBitset bs);
        myBitset& operator/= (myBitset bs);

        bool operator> (const myBitset& bs) const;
        bool operator>= (const myBitset& bs) const;
        bool operator< (const myBitset& bs) const;
        bool operator<= (const myBitset& bs) const;
        bool operator== (const myBitset& bs) const;
        bool operator!= (const myBitset& bs) const;

        explicit operator bool(void) const;
        void flip();// flip all bits
        void set(size_t index);
        void reset(size_t index);
        bool isTrue(size_t index) const;
        size_t getBlock(void) { return block_;}
        size_t getLen(void) { return len_;}
    private:
        size_t* num_;   //pointer to where the bits stored
        const size_t block_;  //the size of the array   
};

template <size_t len_> myBitset<len_>::myBitset(const myBitset<len_>& bs) : 
    block_(bs.block_)
{
    num_ = new size_t[block_];
    for (size_t i = 0; i < bs.block_; i ++) 
        num_[i] = bs.num_[i];
}
// lower bit is stored in the smaller index
template <size_t len_> myBitset<len_>::myBitset(unsigned __int64 num) : myBitset()
{
    size_t p = 0;
//  printf("%llu\n",num);
    while (num && p < len_) {
        if (num & 1) {
            set(p);
//          printf("%d\n",p);
        }
        ++ p;
        num >>= 1;
    }
    // size_t is an unsigned type !!
}
//template <size_t len_> myBitset<len_>::myBitset(unsigned long long num) : 
//  myBitset(unsigned __int64(num)) {}
template <size_t len_> myBitset<len_>::myBitset(unsigned long num) : 
    myBitset(static_cast<unsigned __int64>(num)) {}
template <size_t len_> myBitset<len_>::myBitset(unsigned int num) : 
    myBitset(static_cast<unsigned __int64>(num)) {}

template <size_t len_> myBitset<len_>::myBitset(signed __int64 num) : 
    myBitset(static_cast<unsigned __int64>(abs(num)))
{
    if (num < 0) {
        flip();
        ++ (*this);
    }
}
//template <size_t len_> myBitset<len_>::myBitset(signed long long num) : 
//  myBitset(signed __int64(num)) {}
template <size_t len_> myBitset<len_>::myBitset(signed long num) : 
    myBitset(static_cast<signed __int64>(num)) {}
template <size_t len_> myBitset<len_>::myBitset(signed int num) : 
    myBitset(static_cast<signed __int64>(num)) {}

template <size_t len_> myBitset<len_>::myBitset(const string& s) : myBitset()
{
    for (size_t i = 0; i < s.size(); i ++) {
        if (s[i] != '0') {
            set(s.size() - i - 1);
        }
    }
}
template <size_t len_> myBitset<len_>::~myBitset()
{
    delete []num_;
}

template <size_t len_> inline void myBitset<len_>::set(size_t index)
{
    // 1不加强制类型转换为什么会出现循环左移…… 
    num_[index / BLOCKBIT] |= (size_t(1) << (index % BLOCKBIT));
//  printf("%d %d %d\n",index, index / BLOCKBIT, index % BLOCKBIT);
    return ;
}

template <size_t len_> inline void myBitset<len_>::reset(size_t index)
{
    num_[index / BLOCKBIT] &= ~(size_t(1) << (index % BLOCKBIT));
    return ;
}

template <size_t len_> inline bool myBitset<len_>::isTrue(size_t index) const
{
//  if (num_[index / BLOCKBIT] & (size_t(1) << (index % BLOCKBIT))) printf(" %d %d %d\n",index, index / BLOCKBIT,index %BLOCKBIT);
//  printf("%llu\n",1 << (index % BLOCKBIT));
    return num_[index / BLOCKBIT] & (size_t(1) << (index % BLOCKBIT));
}

template <size_t len_> inline void myBitset<len_>::flip(void)
{
    for (size_t i = 0; i < block_; i ++) {
        num_[i] = ~num_[i];
    }
    return ;
}
template <size_t len_> myBitset<len_>& myBitset<len_>::operator= (const myBitset& bs)
{
    if (this != &bs) {
        for (size_t i = 0; i < block_; i ++)
            num_[i] = bs.num_[i];
    }
}
template <size_t len_> myBitset<len_> myBitset<len_>::operator&(const myBitset& bs) const
{
    myBitset<len_> tbs(*this);
    tbs &= bs;
    return tbs;
}
template <size_t len_> myBitset<len_> myBitset<len_>::operator|(const myBitset& bs) const
{
    myBitset<len_> tbs(*this);
    tbs |= bs;
    return tbs;
}

template <size_t len_> myBitset<len_> myBitset<len_>::operator~(void) const
{
    myBitset<len_> tbs(*this);
    tbs.flip();
    return tbs;
}

template <size_t len_> myBitset<len_> myBitset<len_>::operator^(const myBitset& bs) const
{
    myBitset<len_> tbs(*this);
    tbs ^= bs;
    return tbs;
}

template <size_t len_> myBitset<len_> myBitset<len_>::operator<<(size_t shift) const
{
    myBitset<len_> tbs(*this);
    tbs <<= shift;
    return tbs;
}

template <size_t len_> myBitset<len_> myBitset<len_>::operator>>(size_t shift) const
{
    myBitset<len_> tbs(*this);
    tbs >>= shift;
    return tbs;
}

template<size_t len_> myBitset<len_>& myBitset<len_>::operator&= (const myBitset& bs)
{
    for (size_t i = 0; i < block_; i ++) {
        num_[i] &= bs.num_[i];
    }
    return *this;
}

template<size_t len_> myBitset<len_>& myBitset<len_>::operator|= (const myBitset& bs)
{
    for (size_t i = 0; i < block_; i ++) {
        num_[i] |= bs.num_[i];
    }
    return *this;
}

template<size_t len_> myBitset<len_>& myBitset<len_>::operator^= (const myBitset& bs)
{
    for (size_t i = 0; i < block_; i ++) {
        num_[i] ^= bs.num_[i];
    }
    return *this;
}

template<size_t len_> myBitset<len_>& myBitset<len_>::operator<<= (size_t shift)
{
    if (shift == 0) return *this;
    if (shift >= len_) {
        memset(num_, 0, block_ * sizeof(size_t));
        return *this;
    }
    size_t blockShift = shift / BLOCKBIT; // the shift of how many units of array  
    size_t innerShift = shift % BLOCKBIT; // the shift in the unit of array
    for (size_t i = 0; i < block_; i ++) {
        size_t opid = block_ - 1 - i;
        if (opid < blockShift) {
            num_[opid] = 0;
        } else {
            if (opid - blockShift > 0)
                num_[opid]=(num_[opid-blockShift]<<innerShift)|(num_[opid-blockShift-1]>>(BLOCKBIT-innerShift)); 
            else
                num_[opid] = num_[opid - blockShift] << innerShift;     
        }
    }
    return *this;
}

template<size_t len_> myBitset<len_>& myBitset<len_>::operator>>= (size_t shift)
{
    //  printf("%llu\n",num_[0]);
    if (shift == 0) return *this;
    if (shift >= len_) {
        memset(num_, 0, block_ * sizeof(size_t));
        return *this;
    }
    size_t blockShift = shift / BLOCKBIT; // the shift of how many units of array  
    size_t innerShift = shift % BLOCKBIT; // the shift in the unit of array
    for (size_t i = 0; i < block_; i ++) {
        if (i > block_ - 1 - blockShift) {
            num_[i] = 0;
        } else {
            if (i + blockShift + 1 < block_)
                num_[i]=(num_[i+blockShift]>>innerShift)|(num_[i+blockShift+1]<<(BLOCKBIT-innerShift)); 
            else
                num_[i] = num_[i + blockShift] >> innerShift;       
        }
    }
//  printf("%llu\n",tbs.num_[0]);
    return *this;
}

template <size_t len_>  inline myBitset<len_>& myBitset<len_>::operator++ (void)
{
    (*this) += 1;
    return *this;
}
template <size_t len_>  inline myBitset<len_> myBitset<len_>::operator++ (int dummy)
{
    myBitset<len_> tbs = (*this);
    ++ (*this);
    return tbs;
}
template <size_t len_>  inline myBitset<len_>& myBitset<len_>::operator-- (void)
{
    (*this) -= 1;
    return *this;
}
template <size_t len_>  inline myBitset<len_> myBitset<len_>::operator-- (int dummy)
{
    myBitset<len_> tbs = (*this);
    -- (*this);
    return tbs;
}

template <size_t len_>  inline myBitset<len_> myBitset<len_>::operator+ (const myBitset& bs) const
{
    myBitset<len_> tbs(*this);
    tbs += bs;
    return tbs;
}
template <size_t len_>  inline myBitset<len_> myBitset<len_>::operator- (const myBitset& bs) const
{
    myBitset<len_> tbs(*this);
    tbs += -bs;
    return tbs;
}
template <size_t len_>  inline myBitset<len_>& myBitset<len_>::operator-= (const myBitset& bs)
{
    *this += -bs;
    return *this;
}

template <size_t len_>  inline myBitset<len_>& myBitset<len_>::operator+= (myBitset bs)
{
    myBitset<len_> tbs;
    while ((bs)) {
        tbs = (*this) ^ bs;
        bs = (*this & bs) << 1;
        *this = tbs;
    }
    return *this;
}

template <size_t len_>  inline myBitset<len_> myBitset<len_>::operator+ (void) const
{
    return *this;
}
template <size_t len_>  inline myBitset<len_> myBitset<len_>::operator- (void) const
{
    myBitset<len_> tbs(*this); 
    return ~(tbs) + 1;
}

template<size_t len_> myBitset<len_>::operator bool(void) const
{
    for (size_t i = 0; i < len_ ; i ++) {
        if (isTrue(i))
            return true;
    }
    return false;
}

template <size_t len_>  myBitset<len_>& myBitset<len_>::operator*= (myBitset bs)
{
    if (!bs || !*this) {
        *this = 0;
        return *this;
    }
    int flag = 0;
    myBitset<len_> tbs(*this);
    *this = 0;
    if (isTrue(len_ - 1)) {
        flag = ~flag;
        tbs = -tbs;
    }
    if (bs.isTrue(len_ - 1)) {
        flag = ~flag;
        bs = -bs; 
    }
    while (bs) {
        if (bs & 1) 
            *this += tbs;
        tbs <<= 1;
        bs >>= 1;
    }
    if (flag) {
        *this = -(*this);
    }
    return *this;
}

template <size_t len_>  myBitset<len_> myBitset<len_>::operator* (const myBitset& bs) const
{
    myBitset<len_> tbs(*this);
    tbs *= bs;
    return tbs;
}

template <size_t len_>  myBitset<len_>& myBitset<len_>::operator/= (myBitset bs)
{
//  cout << *this << " " << bs << endl;
    if (bs) {
        int flag = 0;
        myBitset<len_> tbs(*this);
        *this = 0;
        if (tbs.isTrue(len_ - 1)) {
            flag = ~flag;
            tbs = -tbs;
        }
        if (bs.isTrue(len_ - 1)) {
            flag = ~flag;
            bs = -bs; 
        }
//      cout << tbs << " " << bs << endl;
        size_t highbit = 0;
        for (size_t i = len_ - 2; i > 0; i --) {
            if (tbs.isTrue(i)) {
                highbit = i;
                break;
            }
        }
        for (size_t i = 0; i <= highbit; i ++) {
            size_t op = highbit - i;
            // avoid overflow!!!
            if ((tbs >> op) >= bs) {
                tbs -= (bs << op);
                *this += (myBitset<len_>(1) << op);
            }
//          cout << op << " " << tbs << " " << bs << " " << *this << endl;
        }
        if (flag) {
            *this = -(*this);
        }
        return *this;
    } else {
        cout << "divisor cannot be 0 !" << endl;
        return *this;
    }

}
template <size_t len_>  myBitset<len_> myBitset<len_>::operator/ (const myBitset& bs) const
{
    myBitset<len_> tbs(*this);
    tbs /= bs;
    return tbs;
}


template <size_t len_> bool myBitset<len_>::operator>= (const myBitset& bs) const
{
    return (*this > bs || *this == bs);
}
template <size_t len_> bool myBitset<len_>::operator> (const myBitset& bs) const
{
    if (!isTrue(len_ - 1) && isTrue(len_ - 1)) {
        return true;
    } 
    if (isTrue(len_ - 1) && !isTrue(len_ - 1)) {
        return false;
    }

    for (size_t i = 0; i < block_; i ++) {
        size_t op = block_ - i - 1;
        if (num_[op] > bs.num_[op]) {
            return true;
        } 
        if (num_[op] < bs.num_[op]) {
            return false;
        }
    }
    return false;
}
template <size_t len_> bool myBitset<len_>::operator== (const myBitset& bs) const
{
    if (*this ^ bs) {
        return false;
    } else {
        return true;
    }
}
template <size_t len_> inline bool myBitset<len_>::operator< (const myBitset& bs) const
{
    return !(*this >= bs);
}
template <size_t len_> inline bool myBitset<len_>::operator<= (const myBitset& bs) const
{
    return !(*this > bs);
}
template <size_t len_> inline bool myBitset<len_>::operator!= (const myBitset& bs) const
{
    return !(*this == bs);
}

main.cpp
里面主要是测试

#include <iostream>
#include <cmath>
#include "bit.h"
#include <bitset>
using namespace std;

int main(int argc, char** argv) 
{   
    cout << (-11111 >> 30) << endl;
    cout << size_t(-1) << endl;
    cout << "test for set, reset and flip" << endl;
    myBitset<32> bt;
    bt.set(0);
    cout << bt << endl;
    bt.reset(0);
    cout << bt << endl;
    bt.set(31);
    cout << bt << endl;
    bt.flip();
    cout << bt << endl;

    cout << endl << "test for constructor" << endl;
    string s = "100010";
    myBitset<32> bt1;
    cout << bt1 << endl;
    myBitset<33> bt2(s);
    cout << bt2 << endl;
    myBitset<33> bt31(64);
    cout << bt31 << endl;
    myBitset<65> bt32(static_cast<unsigned long long>((size_t(1) << 63) + ((size_t(1) << 63) - 1)));
    cout << bt32 << endl;
    myBitset<33> bt4(bt31);
    cout << bt4 << endl;

    cout << endl << "test for <<, >> and =" << endl;
    myBitset<100> bt5(size_t(pow(2,31))+15);
    cout << bt5 << endl;
    cout << (bt5 << 4) << endl;
    cout << (bt5 >> 4) << endl;
    cout << (size_t(1) << 33) << endl; 
    myBitset<100> bt6("100000011111111111000010101");
    cout << bt6 << endl;
    bt6 = bt5;
    cout << bt6 << endl;
    myBitset<129> bt7 = string("10110011101111011111010101");
    cout << bt7 << endl;
    cout << (bt7 >> 7) << endl;
    cout << (bt7 << 7) << endl;
    cout << (bt7 << 65) << endl;
    cout << (bt7 >> 65) << endl;

    cout << endl << "test for &, |, ~ and ^" << endl;
    myBitset<70> bt8("1011011101111011111011111101111111011111111011111111101111111111011110");
    cout << bt8 << endl;
    myBitset<70> bt9(~bt8);
    cout << bt9 << endl;
    cout << (bt8 | bt9) << endl;
    cout << (bt8 & bt9) << endl;
    cout << (bt8 ^ bt9) << endl;
    cout << (bt8 ^ bt9 ^ bt8) << endl;

    cout << endl << "test for &=, |= and ^=" << endl;
    cout << bt8 << endl;
    bt8 &= bt9;
    cout << bt8 << endl;
    bt8 |= bt9;
    cout << bt8 << endl;
    bt8 ^= ~bt9 ^ 1;
    cout << bt8 << endl;

    cout << endl << "test for <<= and >>=" << endl;
    myBitset<70> bt10("1011011101111011111011111101111111011111111011111111101111111111011111");
    cout << bt10 << endl;
    cout << (bt10 << 65) << endl;
    bt10 <<= 65;
    cout << bt10 << endl;
    bt10 = string("1011011101111011111011111101111111011111111011111111101111111111011111");
    cout << (bt10 >> 65) << endl;
    bt10 >>= 65;
    cout << bt10 << endl;

    cout << endl << "test for + and -" << endl;
    bt9 = string("1011011101111011111011111101111111011111111011111111101111111111011111");
    bt10 = ~bt9;
    cout << bt9 << endl;
    cout << bt10 << endl;
    cout << (-bt9) << endl;
    cout << (-bt10) << endl;
    cout << (bt9 + bt10) << endl;
    cout << (bt9 - (bt10>>3)) << endl;
    bt9 = -1;
    bt10 = 64;
    cout << (bt9 + bt10) << endl;
    cout << (bt9 - bt10) << endl;

    cout << endl << "test for ++, -- , += and -=" << endl;
    bt9 = string("1011011101111011111011111101111111011111111011111111101111111111011111");
    bt10 = ~bt9;
    cout << (bt9 ++) << endl;
    cout << bt9 << endl;
    cout << (bt10 --) << endl;
    cout << bt10 << endl;
    cout << (++ bt9) << endl;
    cout << bt9 << endl;
    cout << (-- bt10) << endl;
    cout << bt10 << endl;
    bt10 += 1;
    cout << bt10 << endl;
    bt10 -= 3;
    cout << bt10 << endl;

    cout << endl << "test for *, *=, /, /=" << endl;
    bt9 = -13;
    bt10 = 3;
    bt9 *= bt10;
    cout << bt9 << endl;
    cout << (bt9 * bt10) << endl;
    bt9 *= -3;
    bt10 *= 100;
    cout << bt9 << endl;
    cout << bt10 << endl;

    cout << endl << "test for /, /=" << endl;
    bt9 = 10;
    bt10 = 3;
    cout << (bt9 >= bt10) << endl;
    cout << (bt9 >> 3) << endl;
    cout << ((bt9 >> 3) >= bt10) << endl;
    cout << (bt9 << 0) << endl;
    cout << (myBitset<70>(1) << 0) << endl;
    bt9 /= bt10;
    cout << bt9 << endl;
    bt9 = -10;
    bt10 = 3;
    cout << (bt9 / bt10) << endl;
    cout << (bt10 / bt9) << endl;

    return 0;
}

附:实验报告

第一次实验报告

一、 题目分析

位运算的封装:
第一次看到这个题目,我想到了stl中的bitset,bitset实现了对bit类型数组的封装,同时支持六种位运算,我的目的就是实现类似于bitset的类模版。
六种位运算& | ~ ^ << >> 支持基础数据类型,但是基础数据类型的大小是固定的,不能支持bit数高于8 * sizeof(size_t)(最大一般是64bit)的要求,而且不能支持任意位数的bit类型数组,这样显然不能满足我们的要求。
因此,我决定使用size_t类型的数组,通过基础类型的位运算实现对每一个size_t内的位的操作,从而实现对抽象的“位类型”的操作。
除了最基础的构造函数、析构函数、拷贝运算符,实现了六种位运算,还实现了布尔类型的类型转换,逻辑运算,和+-*/四则运算和自增自减运算以及流插入操作符重载。

100!的计算:
首先想到的是高精度乘法,通过数组存储大数的每一位,模拟竖式乘法,从而得解。

二、 流程分析(感觉太复杂了画图有些困难,所以通过文字描述)

这里介绍位运算封装的流程,大数阶乘比较简单。
1. 构造函数:
共9个,最基础的是默认构造函数,在其中完成相关变量初始化和内存空间的申请。
之后是拷贝构造函数,myBitset(unsigned __int64 num); myBitset(const string& s); 它们首先使用默认构造函数进行委托构造,之后再实现自己特定的构造。
在之后是以其他各种无符号或有符号整数做参数的构造函数,它们使用myBitset(unsigned __int64 num);进行委托构造,从而完成功能。
2.基础功能的实现
共4个,分别是
void flip();
void set(size_t index);
void reset(size_t index);
bool isTrue(size_t index) const;
flip实现按位取反,set实现对下标是index的置1,reset是实现对下标是index的置0,isTrue判断下标为index的位是否是1,接下来的许多函数都是需要直接或者间接调用这些函数的。
2. 位运算运算符以及=的重载
myBitset& operator= (const myBitset& bs);
myBitset operator& (const myBitset& bs) const;
myBitset operator| (const myBitset& bs) const;
myBitset operator~ (void) const;
myBitset operator^ (const myBitset& bs) const;
myBitset operator<< (size_t shift) const;
myBitset operator>> (size_t shift) const;
myBitset& operator&= (const myBitset& bs);
myBitset& operator|= (const myBitset& bs);
myBitset& operator^= (const myBitset& bs);
myBitset& operator<<= (size_t shift);
myBitset& operator>>= (size_t shift);
首先实现的是&= |= 等函数,之后& |等运算符通过调用&= |= 等实现功能。
3. 四则运算与自增自减
myBitset& operator++ (void);
myBitset& operator– (void);
myBitset operator++ (int dummy);
myBitset operator– (int dummy);
myBitset& operator+= (myBitset bs);
myBitset& operator-= (const myBitset& bs);
myBitset operator+ (const myBitset& bs) const;
myBitset operator- (const myBitset& bs) const;
myBitset operator+ (void) const;
myBitset operator- (void) const;

    myBitset operator* (const myBitset& bs) const;
    myBitset operator/ (const myBitset& bs) const;
    myBitset& operator*= (myBitset bs);
    myBitset& operator/= (myBitset bs);

同样,首先实现的是+= -=等,对应的双目运算符则调用前者,单目-调用~运算符。
前置自增自减调用+= -=,而后置自增自减调用前置自增自减。
4. 逻辑运算符与bool类型转换
bool operator> (const myBitset& bs) const;
bool operator>= (const myBitset& bs) const;
bool operator< (const myBitset& bs) const;
bool operator<= (const myBitset& bs) const;
bool operator== (const myBitset& bs) const;
bool operator!= (const myBitset& bs) const;
explicit operator bool(void) const;
bool类型转换函数调用isTrue函数。
实现的是>和==,其他逻辑运算符直接或间接调用这两个函数。

三、程序难点以及遇到的主要bug

1.构造函数
为了支持四则运算,必须提供参数无符号整型和有符号整型的构造函数,开始我只定义了unsigned __int64和 signed __int64为参数的构造函数,然而这时就会遇到二义调用的问题。
为了避免二义调用,我为常见的整型类型分别定义了构造函数。
2.移位运算
因为存储位的是数组,故实现移位操作时会遇到困难,通过寻找规律可以解决这一问题。
此外还遇到了如下问题。

一开始我并没有对1进行强制类型转换,转换成myBitset类型,按道理,1移位超过int位长时,这样会使1移位后的结果变成0(逻辑移位),但是,这里实际上竟然是循环移位。
而单单对1进行左移位,得到的结果是逻辑移位的结果。
目前还是没有弄明白是为什么。

因为首先实现的是<<=和>>= ,<< >>是通过调用<<= >>= 实现的,移位的时候可能会出现运算结果覆盖未进行运算数据的情况,所以要注意运算的顺序,>>要先从低位开始算,<<要先从高位开始算。

还遇到了移位0时出现的错误,需要特判shift为0时的情况。(除法调用移位操作时发现)
3.bool类型转换
一开始并没有把operator bool 声明为explicit,于是出现了双目运算符调用时的二义调用(左操作数为myBitset对象而右操作数为基础数据类型时),因为myBitset可以隐式的转换为bool类型,c++中bool类型实质上就是int类型。
在查资料之前,我尝试了在声明中加入了explicit关键字,尽管在我的印象中它只能用在构造函数的声明中,但是问题的确解决了,后来查资料发现,在c++11标准中,允许在类型转换运算符前加入explicit的声明,而对bool则更加特殊,在条件表达式中它允许隐式转换而在其他情况中只允许显式使用。
5. 不小心就会发生的间接递归
由于一些运算符要通过调用其他运算符实现,所以在头脑不清晰的情况下极易发生
递归,而且这类错误比较难发现,程序中出现的最长间接递归链甚至可达10个以上的函数。
6. 乘法与除法
在设计乘法的算法时我借鉴了快速幂算法的思想,只不过当第二个乘数为奇数时ans变量做的运算由乘变成了加,只要调用加法就可以实现乘法了。
除法就是乘法的逆运算。
7. size_t类型
size_t类型是一种无符号整数类型,具体类型依赖于环境,但它是非负的,用size_t类型做循环变量时,由于它不可能小于0,于是下面的语句会出现死循环。
For (size_t I = len_ - 1; I >= 0; I ++)
故程序中所有循环尽量写成正序的,需要反向的顺序时,通过循环变量计算出实际运算的下标。

四、 优点与缺点

封装位运算操作符
优点:
a) 实现了任意长度的位类型
b) 满足了所有的要求
c) 尽量使用已定义的方法去定义其他方法
d) 对于多个方法(已实现的或是以后可能实现的)会使用的相同方法,将该方法定义为一个函数
e) 实现了四则运算,自增自减,重载了流插入操作符。
缺点:
a) 最重大的失误:没有将二元运算符用非成员函数实现。(3 + myBitset<10>(1)是非法的)
b) 没有实现[]操作符。(代理模式)
c) 没有用myBitset类实现阶乘(主要是没有转换成整型的方法)
d) 没有定义将myBitset转换为整型的方法(大数进制转换)
e) 部分方法效率不高

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值