12.顶层父类的创建

目录

顶层父类的接口定义

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

小结


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

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

 

不幸的事实

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

new

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

 

创建JQLib::Object类的意义

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

顶层父类的接口定义

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

Object.h
#ifndef OBJECT_H
#define OBJECT_H
#define OBJECT_TEST
namespace JQLib
{
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_H
Object.cpp
#include "Object.h"
#include <cstdlib>
#include <iostream>
using namespace std;
namespace JQLib
{
void* Object::operator new(unsigned int size) throw()
{
    //cout<<"Object::operator new size = "<<size<<endl;
    return malloc(size);
}
void  Object::operator delete(void* p)
{
    //cout<<"Object::operator delete p = "<<p<<endl;
    free(p);
}
void* Object::operator new[] (unsigned int size) throw()
{
    //cout<<"Object::operator new[]"<<endl;
    return malloc(size);
}
void  Object::operator delete[](void* p)
{
    //cout<<"Object::operator delete[]"<<endl;
    free(p);
}
Object::~Object()
{
    //cout<<"Object::~Object()"<<endl;
}
}
main.cpp
#include <iostream>
#include "SmartPointer.h"
#include "Exception.h"
#include "Object.h"
using namespace std;
using namespace JQLib;
#ifdef OBJECT_TEST
class Test : public Object
{
public:
    int i;
    int j;
};
class Child : public Test
{
public:
    int k;
};
int main()
{
    Object* obj1 = new Test();//size = 12==>8+虚函数指针=12
    Object* obj2 = new Child();//size = 16==>8+4+虚函数指针=16
    //....
    cout<<"obj1 = "<<obj1<<endl;
    cout<<"obj2 = "<<obj2<<endl;
    delete obj1;
    delete obj2;
    return 0;
}
#endif

小结

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

 

 

 

 

<think>好的,用户想了解Java中父类初始化的过程或原理。首先,我需要回忆相关的知识,并结合提供的引用资料来整理回答。 根据引用[3],初始化过程是先执行父类构造器<clinit>,然后是子的。构造器包括静态变量和静态代码块的初始化。而对象实例化时,父类的成员变量和实例代码块先于父类构造函数执行,接着才是子的成员变量、实例代码块和构造函数。引用[4]提到,实例化一个时,会先递归实例化其父类,直到Object。每个的实例化顺序是先实例变量和实例代码块,再执行构造函数。同时,编译器会把实例变量和代码块的初始化代码放到构造函数中,放在父类构造函数调用之后,自身构造函数代码之前。 用户的问题可能涉及到初始化和实例初始化两个阶段。需要区分这两个概念。初始化是在加载时进行的,而实例初始化是在创建对象时发生的。父类在这两个阶段中的处理顺序不同。 需要明确步骤:加载时的初始化(静态部分)和对象创建时的初始化(实例部分)。在加载阶段,父类的静态块先执行,然后是子。在对象实例化时,先初始化父类的实例变量和代码块,再执行父类构造函数,之后才是子的实例变量、代码块和构造函数。 可能需要注意用户是否混淆了加载和对象实例化的过程。需要清晰地区分这两个阶段,并分别说明父类在每个阶段中的处理顺序。 另外,引用[1]提到,子对象的隐式初始化依赖于父类的无参构造器,如果没有,必须显式调用父类的有参构造器。这说明在实例化子时,父类构造函数的调用是必须的,否则会报错。这点需要强调,尤其是在构造函数链的调用顺序上。 需要将整个过程分解成步骤,用简明的中文解释,可能结合代码示例来说明各个阶段的执行顺序。例如,静态初始化块、实例初始化块、构造函数的执行顺序,以及父类和子之间的顺序关系。 需要确保回答结构清晰,分点说明,可能使用示例代码来展示执行顺序。同时,引用相关的引用资料来支持解释,例如引用[3]和[4]中的内容。 最后,生成相关问题,帮助用户进一步理解,如初始化与实例化的区别,为什么需要调用父类构造器等。</think>### 父类初始化的过程及原理 Java中父类初始化分为两个阶段:**初始化**(静态初始化)和**实例初始化**(对象创建时的初始化)。以下是详细过程: --- #### 一、初始化(静态初始化) 1. **触发条件** - 首次主动使用时(如创建实例、调用静态方法、访问静态字段等)。 2. **执行顺序** 1. 加载父类父类,递归至最顶层父类(通常是$Object$)[^2]。 2. 从最顶层父类开始,依次执行各父类的静态初始化块($static\ \{ \}$)和静态变量赋值。 3. 最后执行当前的静态初始化块和静态变量赋值[^3]。 ```java class Parent { static { System.out.println("父类静态块"); } } class Child extends Parent { static { System.out.println("子静态块"); } } // 输出顺序:父类静态块 -> 子静态块 ``` --- #### 二、实例初始化(对象创建时的初始化) 当创建对象时,父类实例初始化的流程如下: 1. **触发条件** - 通过$new$关键字实例化子时。 2. **执行顺序** 1. 递归加载父类直至$Object$[^4]。 2. 从最顶层父类开始,依次执行: - **成员变量赋值**和**实例初始化块**(按代码顺序)。 - **构造函数**(若无显式调用,默认调用父类无参构造器)[^1]。 3. 最后执行子的成员变量、实例初始化块和构造函数[^3]。 ```java class Parent { { System.out.println("父类实例块"); } Parent() { System.out.println("父类构造器"); } } class Child extends Parent { { System.out.println("子实例块"); } Child() { System.out.println("子构造器"); } } // 输出顺序: // 父类实例块 -> 父类构造器 -> 子实例块 -> 子构造器 ``` --- #### 三、关键原理 1. **隐式依赖父类无参构造器** 子构造函数首行默认调用$super()$(父类无参构造器)。若父类未定义无参构造器,必须通过$super(...)$显式调用父类有参构造器[^1]。 2. **实例初始化的代码合并** 编译器会将成员变量赋值和实例初始化块的代码合并到构造函数中,顺序为: - 父类构造函数调用($super(...)$)。 - 子成员变量和实例初始化块代码。 - 子构造函数剩余代码[^4]。 --- #### 四、应用示例 ```java class A { static { System.out.println("A静态块"); } { System.out.println("A实例块"); } A() { System.out.println("A构造器"); } } class B extends A { static { System.out.println("B静态块"); } { System.out.println("B实例块"); } B() { System.out.println("B构造器"); } } // 首次创建B对象时输出: // A静态块 -> B静态块 -> A实例块 -> A构造器 -> B实例块 -> B构造器 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值