欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Object

程序员文章站 2022-05-16 14:17:27
...

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

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

2 创建Object类的意义

  • 遵循经典设计准则,所有的数据结构都继承自Object类
  • 定义动态内存申请的行为,提高代码的可移植行

注意: 对于new操作失败,不同的编译器行为不一致。有的编译器会返回null,有的编译器会直接抛出预定义的异常。所以,为了代码的可移植性,有必要统一动态内存申请的行为。可以通过让Object类重载new、delete、new[]、delete[]操作符,然后所有的其他数据结构类都继承自Object类实现。

3 继承关系图和接口实现

顶层父类的接口实现:

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

4 代码实现

Object.h

#ifndef OBJECT_H
#define OBJECT_H

namespace  LemonLib
{
class Object
{
public:
    void* operator new (unsigned int size) throw(); // throw()为异常规格说明,表明当前函数不会抛出任何异常
    void operator delete(void* p);

    void* operator new[](unsigned int size) throw();
    void operator delete[](void *p);

    virtual ~Object() = 0;
    /*
     * 析构函数为纯虚函数主要有如下两个作用:
     *  1.父类为纯虚父类,所有子类都能进行动态类型识别(尤其是用父类指针删除子类对象时,能够调用子类的析构函数)
     *  2.使得父类成为抽象类
     */

};
}

#endif // OBJECT_H

Object.cpp

#include <cstdlib>
#include <iostream>

#include "Object.h"

using namespace std;

namespace LemonLib {
void* Object::operator new (unsigned int size) throw()
{
    cout << "void* Object::operator new (unsigned int size) throw()" << endl;
    return malloc(size);
}

void Object::operator delete(void* p)
{
    cout << "void Object::operator delete(void* p)" << endl;
    free(p);
}

void* Object::operator new[](unsigned int size) throw()
{
    cout << "void* Object::operator new[](unsigned int size) throw()" << endl;
    return malloc(size);
}

void Object::operator delete[](void *p)
{
    cout << "void Object::operator delete[](void *p)" << endl;
    free(p);
}

Object::~Object()
{
    cout << "Object::~Object()" << endl;
}
}

测试代码main.cpp

#include <iostream>
#include "Object.h"

using namespace std;
using namespace LemonLib;

class A : public Object
{
public:
    A()
    {
        cout << "A()" << endl;
    }

    ~A()
    {
        cout << "~A()" << endl;
    }
};

class B : public A
{
public:
    B()
    {
        cout << "B()" << endl;
    }

    ~B()
    {
        cout << "~B()" << endl;
    }
};

int main()
{
    A* a =  new A();
    B* b = new B();

    delete a;
    delete b;
    return 0;
}

输出如下:

void* Object::operator new (unsigned int size) throw()
A()
void* Object::operator new (unsigned int size) throw()
A()
B()
~A()
Object::~Object()
void Object::operator delete(void* p)
~B()
~A()
Object::~Object()
void Object::operator delete(void* p)

由输出结果可以总结出对于b这个对象的构造、析构函数的调用过程如下:

  1. 执行operator new() 函数为其分配空间
  2. operator new() 函数返回会自动调用父类构造函数
  3. 调用自身构造函数
  4. 执行自身析构函数
  5. 执行父类析构函数
  6. 执行operator delete()函数释放为其分配的空间

如上1、2、3为使用new生成对象时的操作,4、5、6为使用delete销毁对象时所进行的操作。