遵循经典设计准则
- DTLib 中的所有类位于单一的继承树
改进的关键点
Exception 类继承自 Object
- 堆空间中创建异常对象失败时,返回NULL指针
新增 InvalidOperationException 异常类
- 成员函数调用时,如果状态不正确则抛出异常
SmartPointer 类继承自 Object 类
- 堆空间中创建智能指针对象失败时,返回NULL指针
编程实验:类族结构的进化
文件:SmartPointer.h
#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H
#include "Object.h"
namespace DTLib
{
template<typename T>
class SmartPointer : public Object // 修改
{
public:
SmartPointer(T *p = nullptr)
{
m_pointer = p;
}
SmartPointer(const SmartPointer &obj)
{
m_pointer = obj.m_pointer;
const_cast<SmartPointer&>(obj).m_pointer = nullptr;
}
SmartPointer &operator= (const SmartPointer &obj)
{
if (this != &obj)
{
delete m_pointer;
m_pointer = obj.m_pointer;
const_cast<SmartPointer&>(obj).m_pointer = nullptr;
}
return *this;
}
T *operator-> ()
{
return m_pointer;
}
T &operator* ()
{
return *m_pointer;
}
bool isNull()
{
return (m_pointer == nullptr);
}
T *get()
{
return m_pointer;
}
~SmartPointer()
{
delete m_pointer;
}
protected:
T *m_pointer = nullptr;
};
}
#endif // SMARTPOINTER_H
文件: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 // 修改
{
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() = 0;
protected:
char *m_message = nullptr;
char *m_location = nullptr;
};
class ArithmeticExcption : public Exception
{
public:
ArithmeticExcption() : Exception(nullptr) { }
ArithmeticExcption(const char *message) : Exception(message) { }
ArithmeticExcption(const char *file, int line) : Exception(file, line) { }
ArithmeticExcption(const char *message, const char *file, int line) : Exception(message, file, line) { }
ArithmeticExcption(const ArithmeticExcption &e) : Exception(e) { }
ArithmeticExcption &operator= (const ArithmeticExcption &e)
{
Exception::operator=(e);
return *this;
}
~ArithmeticExcption() override { }
};
class NullPointerException : public Exception
{
public:
NullPointerException() : Exception(nullptr) { }
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;
}
~NullPointerException() override { }
};
class IndexOutOfBoundsException : public Exception
{
public:
IndexOutOfBoundsException() : Exception(nullptr) { }
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;
}
~IndexOutOfBoundsException() override { }
};
class NoEnoughMemoryException : public Exception
{
public:
NoEnoughMemoryException() : Exception(nullptr) { }
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;
}
~NoEnoughMemoryException() override { }
};
class InvalidParameterExcetion : public Exception
{
public:
InvalidParameterExcetion() : Exception(nullptr) { }
InvalidParameterExcetion(const char *message) : Exception(message) { }
InvalidParameterExcetion(const char *file, int line) : Exception(file, line) { }
InvalidParameterExcetion(const char *message, const char *file, int line) : Exception(message, file, line) { }
InvalidParameterExcetion(const InvalidParameterExcetion &e) : Exception(e) { }
InvalidParameterExcetion &operator= (const InvalidParameterExcetion &e)
{
Exception::operator=(e);
return *this;
}
~InvalidParameterExcetion() override { }
};
class InvalidOpertionExcetion : public Exception // 增加
{
public:
InvalidOpertionExcetion() : Exception(nullptr) { }
InvalidOpertionExcetion(const char *message) : Exception(message) { }
InvalidOpertionExcetion(const char *file, int line) : Exception(file, line) { }
InvalidOpertionExcetion(const char *message, const char *file, int line) : Exception(message, file, line) { }
InvalidOpertionExcetion(const InvalidOpertionExcetion &e) : Exception(e) { }
InvalidOpertionExcetion &operator= (const InvalidOpertionExcetion &e)
{
Exception::operator=(e);
return *this;
}
~InvalidOpertionExcetion() override { }
};
}
#endif // EXCEPTION_H
文件:Exception.cpp (未修改)
#include "Exception.h"
#include <cstring>
#include <cstdlib>
namespace DTLib
{
Exception::Exception(const char *message) : Exception(message, nullptr, 0)
{
}
Exception::Exception(const char *file, int line) : Exception(nullptr, file, line)
{
}
Exception::Exception(const char *message, const char *file, int line)
{
m_message = strdup(message);
if (file != nullptr)
{
char sl[16] = {0};
itoa(line, sl, 10);
m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
m_location = strcpy(m_location, file);
m_location = strcat(m_location, ":");
m_location = strcat(m_location, sl);
}
else
{
m_location = nullptr;
}
}
Exception::Exception(const Exception &e)
{
m_message = strdup(e.m_message);
m_location = strdup(e.m_location);
}
Exception &Exception::operator= (const Exception &e)
{
if (this != &e)
{
free(m_message);
free(m_location);
m_message = strdup(e.m_message);
m_location = strdup(e.m_location);
}
return *this;
}
const char *Exception::message() const
{
return m_message;
}
const char *Exception::location() const
{
return m_location;
}
Exception::~Exception()
{
delete m_message;
delete m_location;
}
}
DTLib 的开发方式和注意事项
迭代开发
- 每次完成一个小的目标,持续开发,最终打造可复用类库
单一继承树
- 所有类都继承自 Object,规范堆对象创建时的行为
只抛异常,不处理异常
- 使用 THROW_EXCEPTION 抛出异常,提高可移植性
弱耦合性
- 尽量不使用标准库中的类和函数,提高可移植性
说明1:只抛异常,不处理异常
背景:有公司会明确规定不允许使用异常处理机制(throw,try,catch)
解决方案:
#define THROW_EXCEPTION(e, m) //(throw e(m, __FILE__, __LINE__))
说明2:尽量不使用标准库中的内容
背景:有公司会明确规定不允许使用标准库
解决方案:当前只在Object文件和Exception文件中使用了malloc,free, strlen, strdup等极少数库函数,这是极其容易被替换的。
第一阶段学习总结
- 数据结构与算法之间的关系
- 算法效率的度量方法
DTLib 的基础设施构建
- 顶层父类
- 智能指针
- 异常类
以上内容整理于狄泰软件学院系列课程,请大家保护原创!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。