当代软件架构实践中的经验

  • 尽量使用单重继承的方式进行系统设计
  • 尽量保持系统中只存在单一的继承树
  • 尽量使用组合关系代替继承关系

不幸的事实

  • C++ 语言的灵活性使得代码可以存在多个继承树
  • C++ 编译器的差异使得同样的代码可能表现不同的行为

new 操作如果失败会发生什么?

  • 老版编译器:返回空
  • 新版编译器:抛出异常

创建 DTLib::Object 类的意义

  • 遵循经典设计准则,所有数据都继承自 Object (单一继承树)
  • 定义动态内存申请的行为,提高代码的移植性(统一编译器行为)

顶层父类的接口定义

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

编程实验:顶层父类的创建

文件:Object.h

#ifndef OBJECT_H
#define OBJECT_H

namespace DTLib
{

class Object
{
public:
    void *operator new (unsigned int size) noexcept;
    void operator delete (void *p);
    void *operator new[] (unsigned int size) noexcept;
    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) noexcept
{
    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) noexcept
{
    return malloc(size);
}

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

Object::~Object()
{
}

}

文件:main.cpp

#include "Object.h"

#include <cstdlib>

#include <iostream>
using namespace std;

namespace DTLib
{

void *Object::operator new (unsigned int size) noexcept
{
    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) noexcept
{
    return malloc(size);
}

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

Object::~Object()
{
}

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

using namespace std;
using namespace DTLib;

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

class Derived : public Base
{
    int k;
};

int main()
{
    Object *obj1 = new Base;
    Object *obj2 = new Derived;

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

    delete obj1;
    delete obj2;

    return 0;
}

输出:

Object::operator new : 12
Object::operator new : 16
obj1 = 0xe66f38
obj2 = 0xe66f50
Object::operator delete : 0xe66f38
Object::operator delete : 0xe66f50

注:C++规定,但凡定义了析构函数,不管析构函数是不是纯虚函数,都需要提供具体实现。(因为父类析构函数需要被子类隐含调用)

小结

  • Object 类是 DTLib 中数据结构类的顶层父类
  • Object 类用于统一动态内存的申请行为
  • 在堆中创建 Object 子类的对象,失败时返回 NULL 值
  • Object 类为纯虚父类,所有子类都能进行动态类型识别

参考课程

狄泰软件学院《C++深度解析教程》

TianSong
734 声望138 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧