本周作业:
为上周题目中的
Fruit
和Apple
添加构造函数与析构函数, 并在构造函数与析构函数中打印控制台信息,观察构造和析枸调用过程。然后为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 <iostream>
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 <iostream>
#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 <iostream>
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 <iostream>
#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
网友评论