頂層父類的構(gòu)建(五)-創(chuàng)新互聯(lián)

  在當(dāng)代的軟件架構(gòu)實(shí)踐中,我們有三條準(zhǔn)則:1、盡量使用單重繼承的方式進(jìn)行系統(tǒng)設(shè)計(jì);2、盡量保持系統(tǒng)中只存在單一的繼承樹;3、盡量使用組合關(guān)系代替繼承關(guān)系。但是由于 C++ 語(yǔ)言的靈活性使得代碼中可以存在多個(gè)繼承樹,C++ 編譯器的差異使得同樣的代碼可能表現(xiàn)不同的行為。

成都創(chuàng)新互聯(lián)是創(chuàng)新、創(chuàng)意、研發(fā)型一體的綜合型網(wǎng)站建設(shè)公司,自成立以來(lái)公司不斷探索創(chuàng)新,始終堅(jiān)持為客戶提供滿意周到的服務(wù),在本地打下了良好的口碑,在過(guò)去的10多年時(shí)間我們累計(jì)服務(wù)了上千家以及全國(guó)政企客戶,如成都木制涼亭等企業(yè)單位,完善的項(xiàng)目管理流程,嚴(yán)格把控項(xiàng)目進(jìn)度與質(zhì)量監(jiān)控加上過(guò)硬的技術(shù)實(shí)力獲得客戶的一致稱譽(yù)。

        我們想下,new 操作如果失敗將會(huì)發(fā)生什么呢?那么肯定會(huì)導(dǎo)致異常嘛,這時(shí)我們便用到了前面構(gòu)建的異常類,此時(shí)我們只需拋出一個(gè)內(nèi)存不足的異常,便會(huì)得到一個(gè)提示。我們這時(shí)便有必要來(lái)創(chuàng)建一個(gè)頂層的父類了,那么創(chuàng)建它的意義在哪呢?一是遵循經(jīng)典設(shè)計(jì)準(zhǔn)則,所有的數(shù)據(jù)結(jié)構(gòu)都繼承自 Object 類,二是定義動(dòng)態(tài)內(nèi)存申請(qǐng)的行為,提高代碼的移植性。下面我們來(lái)看看頂層父類的接口定義,如下所示

class Object
{
public:
    void* operator new (unsigned int size) throw();
    void operator delete (void* p);
    void* operator new[] (unigned int size) throw();
    void operator delete[] (void* p);
    virtual ~Object() = 0;
};

        下來(lái)我們還是以代碼為例來(lái)進(jìn)行實(shí)驗(yàn)

Object.h 源碼


#ifndef OBJECT_H
#define OBJECT_H

namespace DTLib
{

class Object
{
public:
    void* operator new (unsigned int size) throw();
    void operator delete (void* p);
    void* operator new[] (unsigned int size) throw();
    void operator delete[] (void* p);
    virtual ~Object() = 0;
};

}

#endif // OBJECT_H

Object.cpp 源碼

#include "Object.h"
#include <cstdlib>
#include <iostream>

using namespace std;

namespace DTLib
{

void* Object::operator new (unsigned int size) throw()
{
    cout << "Object::operator new : " << size << endl;
    return malloc(size);
}

void Object::operator delete (void* p)
{
    cout << "Object::operator delete : " << p << endl;
    free(p);
}

void* Object::operator new[] (unsigned int size) throw()
{
    return malloc(sizeof(size));
}

void Object::operator delete[] (void* p)
{
    free(p);
}

Object::~Object()
{

}

}

main.cpp 源碼

#include <iostream>
#include "Object.h"

using namespace std;
using namespace DTLib;

class Test : public Object
{
public:
    int i;
    int j;
};

class Child : public Test
{
public:
    int k;
};

int main()
{
    Object* obj1 = new Test();
    Object* obj2 = new Child();

    cout << "obj1 = " << obj1 << endl;
    cout << "obj2 = " << obj2 << endl;

    delete obj1;
    delete obj2;

    return 0;
}

        我們來(lái)看看編譯后的結(jié)果

頂層父類的構(gòu)建(五)

        我們看到在 main 函數(shù)中我們用 Object 父類的指針來(lái)創(chuàng)建了一個(gè) Test 子類對(duì)象和 Child 子類對(duì)象。并且在創(chuàng)建對(duì)象的時(shí)候打印了 Object::operator new ,這很明顯就是調(diào)用了我們自己指定的 malloc 方式。為什么 Test 對(duì)象打印的是 12 呢?因?yàn)樗锩姘藘蓚€(gè) public 成員變量(int),再加上一個(gè)指向虛函數(shù)表的指針,一共是 12 個(gè)字節(jié)。底下的 Child 子類的分析是一樣的。在析構(gòu)的時(shí)候我們看到析構(gòu)時(shí)也打印出了我們寫的 Object::operator delete ,由此可以看出它的析構(gòu)也是調(diào)用的是我們自己定義的。

        下來(lái)我們來(lái)看看經(jīng)典設(shè)計(jì)準(zhǔn)則是怎樣的,如下,我們自己的 DTLib 中華的所有類是位于單一的繼承樹的

頂層父類的構(gòu)建(五)

        我們?cè)倩谏厦鎰?chuàng)建的頂層父類來(lái)改善下我們之前寫的異常類和智能指針(在 C++ 中有介紹過(guò))。

        1、Exception 類繼承自 Object 類。即堆空間中創(chuàng)建異常對(duì)象失敗時(shí)返回 NULL 指針

        2、新增 InvalidOperationException 異常類。在成員函數(shù)調(diào)用時(shí),如果狀態(tài)不正常則拋出異常類

        3、SmartPointer 類繼承自 Object 類。在堆空間中創(chuàng)建智能指針對(duì)象失敗時(shí)返回 NULL 指針

        下來(lái)我們還是以代碼為例來(lái)進(jìn)行說(shuō)明

Exception.h 源碼

#ifndef EXCEPTION_H
#define EXCEPTION_H

#include "Object.h"

namespace DTLib
{

#define THROW_EXCEPTION(e, m) (throw e(m, __FILE__, __LINE__))

class Exception : public Object
{
private:
    char* m_message;
    char* m_location;

    void init(const char* message, const char* file, int line);
public:
    Exception(const char* message);
    Exception(const char* file, int line);
    Exception(const char* message, const char* file, int line);

    Exception(const Exception& e);
    Exception& operator= (const Exception& e);

    virtual const char* message() const;
    virtual const char* location() const;

    virtual ~Exception();
};

class ArithmeticException : public Exception
{
public:
    ArithmeticException() : Exception(0) {}
    ArithmeticException(const char* message) : Exception(message) {}
    ArithmeticException(const char* file, int line) : Exception(file, line) {}
    ArithmeticException(const char* message, const char* file, int line) : Exception(message, file, line) {}

    ArithmeticException(const ArithmeticException& e) : Exception(e) {}
    ArithmeticException& operator= (const ArithmeticException& e)
    {
        Exception::operator =(e);

        return *this;
    }
};

class NullPointerException : public Exception
{
public:
    NullPointerException() : Exception(0) {}
    NullPointerException(const char* message) : Exception(message) {}
    NullPointerException(const char* file, int line) : Exception(file, line) {}
    NullPointerException(const char* message, const char* file, int line) : Exception(message, file, line) {}

    NullPointerException(const NullPointerException& e) : Exception(e) {}
    NullPointerException& operator= (const NullPointerException& e)
    {
        Exception::operator =(e);

        return *this;
    }
};

class IndexOutOfBoundsException : public Exception
{
public:
    IndexOutOfBoundsException() : Exception(0) {}
    IndexOutOfBoundsException(const char* message) : Exception(message) {}
    IndexOutOfBoundsException(const char* file, int line) : Exception(file, line) {}
    IndexOutOfBoundsException(const char* message, const char* file, int line) : Exception(message, file, line) {}

    IndexOutOfBoundsException(const IndexOutOfBoundsException& e) : Exception(e) {}
    IndexOutOfBoundsException& operator= (const IndexOutOfBoundsException& e)
    {
        Exception::operator =(e);

        return *this;
    }
};

class NoEnoughMemoryException : public Exception
{
public:
    NoEnoughMemoryException() : Exception(0) {}
    NoEnoughMemoryException(const char* message) : Exception(message) {}
    NoEnoughMemoryException(const char* file, int line) : Exception(file, line) {}
    NoEnoughMemoryException(const char* message, const char* file, int line) : Exception(message, file, line) {}

    NoEnoughMemoryException(const NoEnoughMemoryException& e) : Exception(e) {}
    NoEnoughMemoryException& operator= (const NoEnoughMemoryException& e)
    {
        Exception::operator =(e);

        return *this;
    }
};

class InvalidParameterException : public Exception
{
public:
    InvalidParameterException() : Exception(0) {}
    InvalidParameterException(const char* message) : Exception(message) {}
    InvalidParameterException(const char* file, int line) : Exception(file, line) {}
    InvalidParameterException(const char* message, const char* file, int line) : Exception(message, file, line) {}

    InvalidParameterException(const InvalidParameterException& e) : Exception(e) {}
    InvalidParameterException& operator= (const InvalidParameterException& e)
    {
        Exception::operator =(e);

        return *this;
    }
};

class INvalidOPerationException : public Exception
{
public:
    INvalidOPerationException() : Exception(0) {}
    INvalidOPerationException(const char* message) : Exception(message) {}
    INvalidOPerationException(const char* file, int line) : Exception(file, line) {}
    INvalidOPerationException(const char* message, const char* file, int line) : Exception(message, file, line) {}

    INvalidOPerationException(const INvalidOPerationException& e) : Exception(e) {}
    INvalidOPerationException& operator= (const InvalidParameterException& e)
    {
        Exception::operator =(e);

        return *this;
    }
};

}

#endif // EXCEPTION_H

Exception.cpp 源碼

#include "Exception.h"
#include <cstring>
#include <cstdlib>

using namespace std;

namespace DTLib
{

void Exception::init(const char* message, const char* file, int line)
{
    m_message = (message ? strdup(message) : NULL);

    if( file != NULL )
    {
        char s1[16] = {0};

        itoa(line, s1, 10);

        m_location = static_cast<char*>(malloc(strlen(file) + strlen(s1) + 2));
        m_location = strcpy(m_location, file);
        m_location = strcat(m_location, ":");
        m_location = strcat(m_location, s1);
    }
    else
    {
        m_location = NULL;
    }
}

Exception::Exception(const char* message)
{
    init(message, NULL, 0);
}

Exception::Exception(const char* file, int line)
{
    init(NULL, file, line);
}

Exception::Exception(const char* message, const char* file, int line)
{
    init(message, file, line);
}

Exception::Exception(const Exception& e)
{
    m_message = e.m_message;
    m_location = e.m_location;
}

Exception& Exception::operator= (const Exception& e)
{
    if( this != &e )
    {
        free(m_message);
        free(m_location);

        m_message = e.m_message;
        m_location = e.m_location;
    }

    return *this;
}

const char* Exception::message() const
{
    return m_message;
}

const char* Exception::location() const
{
    return m_location;
}

Exception::~Exception()
{
    free(m_message);
    free(m_location);
}

}

SmartPointer.h 源碼

#ifndef SMARTPOINTER_
H#define SMARTPOINTER_H

#include "Object.h"

namespace DTLib
{

template < typename T >
class SmartPointer : public Object
{
private:
    T* m_pointer;
public:
    SmartPointer(T* p = NULL)
    {
        m_pointer = p;
    }

    SmartPointer(const SmartPointer<T>& obj)
    {
        m_pointer = obj.m_pointer;

        const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;
    }

    SmartPointer<T>& operator= (const SmartPointer<T>& obj)
    {
        if( this != &obj )
        {
            delete m_pointer;

            m_pointer = obj.m_pointer;

            const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;
        }

        return *this;
    }

    T* operator-> ()
    {
        return m_pointer;
    }

    T& operator* ()
    {
        return *m_pointer;
    }

    bool isNull()
    {
        return (m_pointer == NULL);
    }

    T* get()
    {
        return m_pointer;
    }

    ~SmartPointer()
    {
        delete m_pointer;
    }
};

}

#endif // SMARTPOINTER_H

main.cpp 源碼

#include <iostream>
#include "SmartPointer.h"
#include "Exception.h"

using namespace std;
using namespace DTLib;

int main()
{
    SmartPointer<int>* p = new SmartPointer<int>();

    delete p;

    INvalidOPerationException* e = new INvalidOPerationException();

    delete e;

    return 0;
}

        我們?cè)?Object 頂層父類中的 new 和 delete 函數(shù)中搭上斷點(diǎn),同時(shí)也在 main 函數(shù)中的 SmartPointer 和 INvalidOPerationException 的 new 和 delete 操作中打上斷點(diǎn),看看程序的執(zhí)行流,如下

頂層父類的構(gòu)建(五)

頂層父類的構(gòu)建(五)

        第一幅圖是執(zhí)行 SmartPointer 指針的 new 和 delete 操作時(shí)輸出的信息,第二幅圖是執(zhí)行 INvalidOPerationException 指針的 new 和 delete 操作時(shí)輸出的信息。我們可以看到調(diào)用的 new 和 delete 操作都是 Object 中的函數(shù)。也就是說(shuō),我們現(xiàn)在的所有操作都是基于 Object 頂層父類的,由它統(tǒng)一 new 和 delete 的行為操作。我哦們?cè)谶M(jìn)行 DTLib 庫(kù)的開發(fā)時(shí)需要注意:1、迭代 開發(fā):也就是每次完成一個(gè)小目標(biāo),持續(xù)開發(fā),最終打造可復(fù)用類庫(kù);2、單一繼承樹:所有樹都繼承自 Object,規(guī)范堆對(duì)象創(chuàng)建時(shí)的行為;3、只拋異常,不處理異常:使用 THROW_EXCEPTION 拋出異常,提高可移植性;4、弱耦合性:盡量不適應(yīng)標(biāo)準(zhǔn)庫(kù)中的類和函數(shù),提高可移植性。通過(guò)今天的學(xué)習(xí),總結(jié)如下:1、Object 類是 DTLib 庫(kù)中數(shù)據(jù)結(jié)構(gòu)類的頂層父類;2、Object 類用于統(tǒng)一動(dòng)態(tài)內(nèi)存申請(qǐng)的行為;3、在堆中創(chuàng)建 Object 子類的對(duì)象,失敗時(shí)返回 NULL 值;4、頂層父類的構(gòu)建(五)Object 類為純虛父類,所有子類都能進(jìn)行動(dòng)態(tài)類型識(shí)別。至此我們的庫(kù)的基礎(chǔ)設(shè)施構(gòu)建基本已經(jīng)完成:頂層父類、智能指針、異常類。


另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

網(wǎng)站名稱:頂層父類的構(gòu)建(五)-創(chuàng)新互聯(lián)
本文URL:http://muchs.cn/article40/dgejeo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、電子商務(wù)外貿(mào)網(wǎng)站建設(shè)、靜態(tài)網(wǎng)站、Google、小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)