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);
}
}

时间: 2024-07-29 11:13:54

Cpp数据结构实战开发2-基本类的构建的相关文章

Android软硬整合设计与框架揭秘: HAL&amp;Framework &amp;Native Service &amp;App&amp;HTML5架构设计与实战开发

掌握Android从底层开发到框架整合技术到上层App开发及HTML5的全部技术: 一次彻底的Android架构.思想和实战技术的洗礼: 彻底掌握Andorid HAL.Android Runtime.Android Framework.Android Native Service.Android Binder.Android App.Android Testing.HTML5技术的源泉和精髓等核心技术,不仅仅是技术和代码本身,更重要的是背后的设计思想和商业哲学. 一.课程特色 l  贯通And

Lucene4.6+Solr4.6实战开发垂直搜索引擎 Lucene4.6实战视频教程

<基于Lucene4.6+Solr4.6+Heritrix1.14+S2SH实战开发从无到有垂直搜索引擎> 课程讲师:小叶子 课程分类:Java 适合人群:初级 课时数量:69课时 用到技术:Hibernate.Struts.Spring.jQuery.Lucene.Solr.Heritrix 涉及项目:百度文库搜索引擎 垂直搜索引擎是针对某一个行业的专业搜索引擎,是搜索引擎的细分和延伸,是对网页库中的某类专门的信息进行一次整合,定向分字段抽取出需要的数据进行处理后再以某种形式返回给用户.垂直

【课程分享】基于Lucene4.6+Solr4.6+Heritrix1.14+S2SH实战开发从无到有垂直搜索引擎

对这个课程有兴趣的朋友,能够加我的QQ2059055336和我联系,能够和您分享. 课程介绍:最有前途的软件开发技术--搜索引擎技术 搜索引擎作为互联网发展中至关重要的一种应用,已经成为互联网各个领域的制高点,其重要性不言而喻.搜索引擎领域也是互联网应用中不多见的以核心技术作为其命脉的领域,搜索引擎各个子系统是怎样设计的?这成为广大技术人员和搜索引擎优化人员密切关注的内容. 随着互联网行业兴起,大数据时代的到来,搜索引擎开发成为一项极富含金量的工作,市场对搜索软件开发project师的需求极其旺

Extjs视频教程_快速上手Extjs4.2实战开发

Extjs视频教程_快速上手Extjs4.2实战开发快速上手Extjs4.2并熟练搭建基于MVC4+FluentData+Spring.net和T4模板的企业级项目架构适合人群:中级课程分类:.NET+ExtJs课时数量:76课时用到技术:Extjs4.2,MVC4,FluentData,T4,Spring.net涉及项目:基于Extjs4.2的丰富案例.一个独立的企业级架构和综合演示案例咨询qq:1840215592 Extjs视频教程课程大纲:(1)Extjs4.2理论部分(风舞烟老师老师主

[转]【全面解禁!真正的Expression Blend实战开发技巧】第六章 认识ListBox

反反复复考虑后,准备把这一章的切入点瞄准ListBox.并用了一个看起来有点别扭的标题“认识ListBox",许多人看到这里就不爱看了,即使是大学里用winform的学生也会说ListBox我看他好几年了.但我想说,在实际项目开发中,界面元素除了Button,另一个使用率最高的就是ListBox,你认识ListBox,但未必认识下面几种特殊的ListBox,也未必知道如何最快速构建这样特殊的ListBox,这背后还涉及了blend独有的很重要的一个元素的用法,sampledatasource!有

零基础Swift实战开发视频教程_从入门到精通

零基础Swift实战开发从入门到精通(4大项目实战.酷跑熊猫.百度音乐.足球游戏等)适合人群:初级课时数量:50课时更新程度:86%用到技术:Swift涉及项目:酷跑熊猫.百度音乐.足球游戏咨询qq:1840215592零基础Swift实战开发视频教程采用基础+项目的方式进行讲解,通过基础的学习,可以完全掌握Swift基本语法应用,并结合4个项目进行开发,学员能在最短的时间内掌握开发的各项技能. 零基础Swift实战开发从入门到精通详细查看:http://www.ibeifeng.com/goo

SSH+ExtJS实战开发视频教程

基于S2SH+ExtJS4+Oracle9i技术实战开发电子商业汇票系统 课程分类:Java+ExtJs 适合人群:中级 课时数量:41课时 用到技术:Hibernate.Struts.Spring.Extjs 涉及项目:电子商业汇票系统 咨询QQ:1840215592 一.电子商业汇票系统简介: 是指出票人依托电子商业汇票系统,以数据电文形式制作的,委托付款人在指定日期无条件支付确定的金额给收款人或者持票人的票据.即实现商业汇票业务操作完全电子化,在业务操作的过程中,没有实物票据的流转,全部是

Extjs视频教程_Extjs5.0从入门到实战开发信息管理系统

Extjs5.0从入门到实战开发信息管理系统(Extjs基础.Extjs5新特性.Spring.Spring mvc.Mybatis)适合人群:初级课时数量:40课时用到技术:Extjs基础,Extjs5新特性,sencha cmd,spring,spring mvc, mybatis涉及项目:信息管理系统核心框架(mvvm+mvc架构)咨询qq:1840215592课程内容简介:1.课程研发环境开发工具:eclipse,sencha cmd:数据库工具:mysql5,mysql workben

Extjs5.0从入门到实战开发信息管理系统(Extjs基础、Extjs5新特性、Spring、Spring mvc、Mybatis)视频教程

Extjs5.0从入门到实战开发信息管理系统(Extjs基础.Extjs5新特性.Spring.Spring mvc.Mybatis)视频教程下载   联系QQ:1026270010 Extjs作为一款优秀的JS前端开发框架以其良好的架构.丰富的UI组件库.完善的文档和社区支持等诸多优点拥有广泛的市场应用空间,开发人员无需过多的关注HTML.CSS甚至各种常用JS算法,只需把精力放在业务逻辑上,利用各种组件的相互组合调用便可轻松而高效的开发出系统的前端页面. Extjs5在之前版本的基础上又推出