Cpp數據結構實戰開發2-基本類的構建
阿新 • • 發佈:2017-11-18
isnull 頭文件 原則 get() 對象創建 sage 機制 重載操作符 else
- 構建自己的類庫,MxLib
叠代開發
單一繼承樹:所有類繼承自Object類,規範堆對象創建時的行為
只拋異常,不處理:使用宏拋出異常,提高可移植性
弱耦合性:盡量不使用標準庫中的類和函數,提高可移植性
頂層父類
- 軟件架構實踐經驗:
盡量使用單重繼承的方式進行系統設計
盡量保持系統中只存在單一的繼承樹
盡量使用組合關系代替繼承關系
在MxLib中創建Objec類,所有類都繼承自MxLib::Object類,統一定義動態內存申請和銷毀的行為
頭文件 Object.h
#ifndef OBJECT_H
#define OBJECT_H
namespace MxLib
{
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.cpp
#include "Object.h"
#include <cstdlib> // 可以根據實際的需要更換頭文件
namespace MxLib
{
void* Object::operator new(unsigned int size) throw() // 申請內存失敗不會拋異常,返回 NULL
{
return malloc(size);
}
void Object::operator delete(void* p)
{
free(p);
}
void* Object::operator new[](unsigned int size) throw() // 申請內存失敗不會拋異常,返回 NULL
{
return malloc(size);
}
void Object::operator delete[](void* p)
{
free(p);
}
// 父類的析構函數即使是純虛函數也要提供實現
Object::~Object(){}
}
智能指針
- 使用目的
智能指針最大程度上避免堆空間內存泄露問題 - 特點
指針生命周期結束時主動釋放堆空間
智能指針只能用於指向堆空間中的內存
重載指針特征符(-> 和 *)能夠使用對象代替指針
最多由一個指針標識指向一片堆空間 - 註意
杜絕指針指針的運算和比較
智能指針智能用來指向堆空間的單個對象或變量
頭文件 SmartPointer.h
#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H
#include "Object.h"
namespace MxLib
{
template <typename T>
class SmartPointer : public Object
{
protected:
T* pointer;
public:
SmartPointer(T* pointer = NULL)
{
this->pointer = pointer;
}
/**
* 在拷貝構造函數和重載賦值操作符中,使一個指針標識最多指向一片堆空間
*/
SmartPointer(const SmartPointer<T>& obj)
{
this->pointer = obj.pointer;
const_cast<SmartPointer<T>&>(obj).pointer = NULL;
}
SmartPointer<T>& operator = (const SmartPointer<T>& obj)
{
if (this != &obj)
{
delete this->pointer;
this->pointer = obj.pointer;
const_cast<SmartPointer<T>&>(obj).pointer = NULL;
}
return *this;
}
/**
* 重載指針特征符(-> 和 *)能夠使用對象代替指針
*/
T* operator -> ()
{
return this->pointer;
}
T& operator * ()
{
return *(this->pointer);
}
bool isNull() {
return (this->pointer == NULL);
}
T* get() {
return this->pointer;
}
~SmartPointer() // 只能用來指向堆空間中的單個變量或對象
{
delete this->pointer;
}
};
}
#endif // SMARTPOINTER_H
異常類
使用異常機制能分離代碼的正常邏輯和異常邏輯
類類型異常的匹配依舊是至上而下嚴格匹配,符合賦值兼容性原則
一般匹配子類異常的catch放在上部;匹配父類的放下部
頭文件 Exception.h
#ifndef EXCEPTION_H
#define EXCEPTION_H
#include "Object.h"
namespace MxLib
{
// 使用宏簡化代碼
#define THROW_EXCEPTION(e, m) (throw e(m, __FILE__, __LINE__))
class Exception : public Object
{
protected:
char* message;
char* 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* getMessage() const;
virtual const char* getLocation() const;
// 父類的析構函數即使是純虛函數也要提供實現
virtual ~Exception() = 0;
};
/**
計算異常
*/
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 InvalidOpeartionException : public Exception
{
public:
InvalidOpeartionException() : Exception(0) {}
InvalidOpeartionException(const char* message) : Exception(message) {}
InvalidOpeartionException(const char* file, int line) : Exception(file, line) {}
InvalidOpeartionException(const char* message, const char* file, int line) : Exception(message, file, line) {}
InvalidOpeartionException(const InvalidOpeartionException& e) : Exception(e) {}
InvalidOpeartionException& operator = (const InvalidOpeartionException& e)
{
Exception::operator = (e);
return *this;
}
};
}
#endif // EXCEPTION_H
源文件 Exception.cpp
#include "Exception.h"
#include <cstring>
#include <cstdlib>
using namespace std;
namespace MxLib
{
void Exception::init(const char* message, const char* file, int line)
{
//無法確定 message 字符串的所處的內存空間,需要在堆空間中拷貝 message 字符串以保證
this->message = strdup(message);
if(NULL != file)
{
char sl[16] = {0};
// 把行號轉為字符存放在sl數組裏
itoa(line, sl, 10);
this->location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
// 動態內存申請失敗不采取行動
if (NULL != this->location)
{
this->message =strcpy(this->message, file);
this->message=strcat(this->message, ":");
this->message=strcat(this->message, sl);
}
}
else
{
this->location = NULL;
}
}
Exception::Exception(const char* message)
{
init(message, NULL, 0);
}
Exception::Exception(const char* file, int line)
{
init(NULL, file, 0);
}
Exception::Exception(const char* message, const char* file, int line)
{
init(message, file, line);
}
/**
* 拷貝構造函數和賦值重載符使用深拷貝
*/
Exception::Exception(const Exception& e)
{
this->message = strdup(e.message);
this->location = strdup(e.location);
}
Exception& Exception::operator= (const Exception& e)
{
if (this != &e)
{
free(this->message);
free(this->location);
this->message = strdup(e.message);
this->location = strdup(e.location);
}
return *this;
}
const char* Exception::getMessage() const
{
return this->message;
}
const char* Exception::getLocation() const
{
return this->location;
}
Exception::~Exception()
{
free(this->message);
free(this->location);
}
}
Cpp數據結構實戰開發2-基本類的構建