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这个对象的构造、析构函数的调用过程如下:
- 执行operator new() 函数为其分配空间
- operator new() 函数返回会自动调用父类构造函数
- 调用自身构造函数
- 执行自身析构函数
- 执行父类析构函数
- 执行operator delete()函数释放为其分配的空间
如上1、2、3为使用new生成对象时的操作,4、5、6为使用delete销毁对象时所进行的操作。
推荐阅读
-
深入剖析JavaScript:Object类型
-
Object.assign()扩展之实现原型链拷贝
-
Python判断对象是否为文件对象(file object)的三种方法示例
-
JavaScript中的Object对象学习教程
-
什么是DOM(Document Object Model)文档对象模型
-
JS数组Object.keys()方法的使用示例
-
PHP错误Cannot use object of type stdClass as array in错误的解决办法
-
php object转数组示例
-
轻松掌握JavaScript中的Math object数学对象
-
浅析JavaScript中的对象类型Object