Cpp数据结构实战开发2-基本类的构建
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cpp数据结构实战开发2-基本类的构建相关的知识,希望对你有一定的参考价值。
- 构建自己的类库,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-基本类的构建的主要内容,如果未能解决你的问题,请参考以下文章
[Java 并发编程实战] 设计线程安全的类的三个方式(含代码)
Express实战 - 应用案例- realworld-API - 路由设计 - mongoose - 数据验证 - 密码加密 - 登录接口 - 身份认证 - token - 增删改查API(代码片段