Boolan C++面向对象高级程序设计-第五周作业

本周作业:

为上周题目中的FruitApple添加构造函数与析构函数, 并在构造函数与析构函数中打印控制台信息,观察构造和析枸调用过程。然后为Apple类重载::operator new::operator delete,在控制台打印信息,并观察调用结果。

于是首先添加构造函数和析构函数,然后观察构造和析构调用过程。
这部分的Fruit和Apple类我都放在一个叫做fruit.h的头文件里。

//
// Created by laixi on 2018/4/22.
//

#ifndef WEEK5HM_FRUIT_H
#define WEEK5HM_FRUIT_H

#include 

class Fruit{
public:
    int no;
    double weight;
    char key;
public:
    void print() {}
    virtual void process(){}
    Fruit() {
        std::cout << "Fruit::Fruit() ctor\n";
    }
    virtual ~Fruit() {
        std::cout << "Fruit::~Fruit() dtor\n";
    }
};

class Apple: public Fruit{
public:
    int size;
    char type;
public:
    void save() {}
    virtual void process(){}
    Apple():Fruit() {
        std::cout << "Apple::Apple() ctor\n";
    }
    ~Apple() {
        std::cout << "Apple::~Apple() dtor\n";
    }
};

#endif //WEEK5HM_FRUIT_H

其中fruit作为父类,他的析构函数是虚函数的。
那么在main函数中测试的代码就分别生成Apple和Fruit的实例就可以看出来了。
主程序代码是:

#include 
#include "fruit.h"

int main() {
    std::cout << "sizeof(Fruit)=" << sizeof(Fruit) << std::endl;
    std::cout << "sizeof(Apple)=" << sizeof(Apple) << std::endl;
    std::cout << "instantiation f, an object of Fruit\n";
    Fruit *f = new Fruit();
    std::cout << "instantiation a, an object of Apple\n";
    Apple *a = new Apple();
    std::cout << "deconstruction of Apple\n";
    delete a;
    std::cout << "deconstruction of Fruit\n";
    delete f;
    return 0;
}

运行的结果是:

sizeof(Fruit)=32
sizeof(Apple)=40
instantiation f, an object of Fruit
Fruit::Fruit() ctor
instantiation a, an object of Apple
Fruit::Fruit() ctor
Apple::Apple() ctor
deconstruction of Apple
Apple::~Apple() dtor
Fruit::~Fruit() dtor
deconstruction of Fruit
Fruit::~Fruit() dtor

很显然,子类在构造的时候会预先构造它的父类,然后再调用自身的构造函数。

按照题意,接下来将operator new()和operator delete()也进行重载

//
// Created by laixi on 2018/4/22.
//

#ifndef WEEK5HM_FRUIT_H
#define WEEK5HM_FRUIT_H

#include 

class Fruit{
public:
    int no;
    double weight;
    char key;
public:
    void print() {}
    virtual void process(){}
    Fruit() {
        std::cout << "Fruit::Fruit() ctor\n";
    }
    virtual ~Fruit() {
        std::cout << "Fruit::~Fruit() dtor\n";
    }
    static void* operator new(size_t size) {
        Fruit* p = (Fruit*) malloc(size);
        std::cout << "Fruit::operator new(), size=" << size << ", return:" << p << std::endl;
        return p;
    }
    static void operator delete(void* pdead, size_t size) {
        std::cout << "Fruit::operator delete(), size=" << size << ", pdead=" << pdead << std::endl;
        free(pdead);
    }
};

class Apple: public Fruit{
public:
    int size;
    char type;
public:
    void save() {}
    virtual void process(){}
    Apple():Fruit() {
        std::cout << "Apple::Apple() ctor\n";
    }
    ~Apple() {
        std::cout << "Apple::~Apple() dtor\n";
    }
    static void* operator new(size_t size) {
        Apple* p = (Apple*) malloc(size);
        std::cout << "Apple::operator new(), size=" << size << ", return:" << p << std::endl;
        return p;
    }
    static void operator delete(void* pdead, size_t size) {
        std::cout << "Apple::operator delete(), size=" << size << ", pdead=" << pdead << std::endl;
        free(pdead);
    }
};
};


#endif //WEEK5HM_FRUIT_H

主程序改为

#include 
#include "fruit.h"

int main() {
    std::cout << "sizeof(Fruit)=" << sizeof(Fruit) << std::endl;
    std::cout << "sizeof(Apple)=" << sizeof(Apple) << std::endl;
    std::cout << "instantiation f, an object of Fruit\n";
    Fruit *f = new Fruit();
    std::cout << "Fruit           = " << f << std::endl;
    std::cout << "Fruit.no        = " << &f->no << std::endl;
    std::cout << "Fruit.weight    = " << &f->weight << std::endl;
    printf("Fruit.key       = 0x%x\n",&(f->key));
    std::cout << "instantiation a, an object of Apple\n";
    Apple *a = new Apple();
    std::cout << "Apple           = " << a << std::endl;
    std::cout << "Apple.no        = " << &a->no << std::endl;
    std::cout << "Apple.weight    = " << &a->weight << std::endl;
    printf("Apple.key       = 0x%x\n",&(a->key));
    std::cout << "Apple.size      = " << &a->size << std::endl;
    printf("Apple.type      = 0x%x\n",&(a->type));
    std::cout << "deconstruction of Apple\n";
    delete a;
    std::cout << "deconstruction of Fruit\n";
    delete f;
    return 0;
}

输出将变为

sizeof(Fruit)=32
sizeof(Apple)=40
instantiation f, an object of Fruit
Fruit::operator new(), size=32, return:0x2727a20
Fruit::Fruit() ctor
Fruit           = 0x2727a20
Fruit.no        = 0x2727a28
Fruit.weight    = 0x2727a30
Fruit.key       = 0x2727a38
instantiation a, an object of Apple
Apple::operator new(), size=40, return:0x2727d90
Fruit::Fruit() ctor
Apple::Apple() ctor
Apple           = 0x2727d90
Apple.no        = 0x2727d98
Apple.weight    = 0x2727da0
Apple.key       = 0x2727da8
Apple.size      = 0x2727dac
Apple.type      = 0x2727db0
deconstruction of Apple
Apple::~Apple() dtor
Fruit::~Fruit() dtor
Apple::operator delete(), size=40, pdead=0x30f7d90
deconstruction of Fruit
Fruit::~Fruit() dtor
Fruit::operator delete(), size=32, pdead=0x30f7a20

可以看到,重载之后,成员new的操作和delete的操作就替换为我们提供的版本了。

在这个子类和父类重载函数的编写过程中,出现过一个奇特的点。我忘记写Apple的Operator delete()了。这个时候的运行过程,会发现Apple的析构会调用父类的析构函数。
程序执行结果的最后四行就变成了

Fruit::operator delete(), size=40, pdead=0x30f7d90
deconstruction of Fruit
Fruit::~Fruit() dtor
Fruit::operator delete(), size=32, pdead=0x30f7a20

你可能感兴趣的:(Boolan C++面向对象高级程序设计-第五周作业)