1. 程式人生 > >面向物件程式設計第一次實驗課——位運算封裝

面向物件程式設計第一次實驗課——位運算封裝

題目的大意是用一個類封裝位運算,並通過位運算實現四則運算。我一下子就想起了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) 部分方法效率不高