Boolan c++面向对象下 第二周笔记


在上图中,c继承b,b集成a。在class A 中包含m_data1和m_data2以及一个指针。

Class B,继承了A,因此B中除了自己的m_data3外,还包含了class A的所有内容,class C也同理。

在一个类中,若有一个虚函数,内存中有一个指针,若有一万个虚函数,内存中依然有一个指针

在继承关系中,子类不仅继承了父类的所有数据,也继承了父类的函数,准确的说是父类函数中的调用权。没有人可以说清楚父类中的函数占用多大的内存。

 

在上图右边,class A有2个虚函数,2个普通函数,因此,class B中也同样拥有两个虚函数(继承),但是B中重写了其中一个虚函数。另外B中也有一个普通函数(虽然与父类同名,但是是两个不同的函数)class C同理。

因此在ABC三个类中,共有4个虚函数4个普通函数

Class A中的虚指针指向一个虚表(vtbl),虚表中存放的都是函数指针,指向虚函数存放的位置。Class A中有两个虚函数,因此虚表中就有两个指针分别指向两个虚函数。

 

当我们new一个class C的时候就会产生一个指向class C 的指针p,如果我们想通过指针p调用class C的一个虚函数应该怎么调用呢?

思路是这样的,通过指针p找到虚表,然后通过虚表中该函数的位置n(编译时函数出现的顺序),再找到该函数。


总结:满足以下条件,即动态绑定:a. 指针b. 向上转型(指针指的是子类)c.调用虚函数

向上转型解释:例如,class B 继承A。A* pa=new B; pa是指向子类B的指针,但pa是A的对象,由子类B向A转型。



Const 再谈

对于数据,我们有const和non-const两种,对于成员函数,我们也有const和non-const两种。在这种情况下,这四种东西有如下表所示的关系:


在我们设计成员函数的时候,若我们本意是不改变数据而忘了加const的时候,在调用成员函数而对于object加了const的时候(常量对象调用非常量函数),就会发生冲突而导致错误。

 

 

New 和 Delete

Array new 一定要搭配array delete

可以重载operator new、operator delete、operator new[]、operator delete[]

Inline void* operator new (size_t size){ }

Inline void* operator new [](size_t size){}

Inline void operator delete (void* ptr){ }

Inline void operator delete [] (void* ptr){}


本周作业体会

本周作业分为两个部分

(1)      是在上周的基础上添加构造函数和析构函数,然后观察构造和析构函数的调用过程。

这里头文件代码设计如下:

#ifndef__FRUIT__

#define__FRUIT__

#include<iostream>

usingnamespace std;

classFruit

{

   int no;

   double weight;

   char key;

public:

   Fruit() { cout << "The defaultFruit ctor.this= "

            << this << endl; }

   virtual ~Fruit() {

            cout << "The Fruitdtor.this= "

                     << this <<endl;

   }

   void print(){}

   virtual void process(){}

};

 

classApple :public Fruit

{

   int size;

   char type;

public:

   Apple(){cout<<"The default Applector.this= "

            << this << endl;}

   virtual ~Apple() {

            cout << "The Appledtor.this= "

                     << this <<endl;

   }

   void save(){}

   virtual void process(){}

};

 

#endif

 

源代码如下:

#include<iostream>

#include"week_5.h"

intmain()

{

   Fruit my_fruit;

   cout <<"*************************" << endl;

   Fruit *p = new Fruit();

   delete p;

   cout <<"*************************" << endl;

   Apple my_apple;

   cout <<"*************************" << endl;

   Fruit *q = new Apple();

   delete q;

   cout <<"*************************" << endl;

   Apple *x = new Apple();

   delete x;

  

}

 

在测试代码中分别设计了五种对象的创建

A)     在栈中创建fruit,

B)     在堆中创建fruit

C)     在栈中创建apple

D)     在堆中创建apple,用父类指针指向它

E)      在堆中创建apple,用子类指针指向它

经编译,结果如下;


结果分析如下:

A)     在栈中创建父类对象时,调用父类构造函数,其析构函数在程序最终结束前才进行调用

B)     在堆中创建父类对象时,调用父类构造函数,再调用析构函数

C)     在栈中创建子类对象时,先调用父类构造函数,再调用子类构造函数,指针指向相同地址。调用析构时同样发生在程序结束时,先调用子类析构函数,再调用父类析构函数。最后调用的析构函数是最先调用的构造函数。

D)     和E)中在堆中创建子类对象时,先调用父类构造函数,再调用子类构造函数,指针指向相同地址,接着先调用子类析构函数,再调用父类析构函数

在D和E中发生的事情一模一样,但是在堆中创建apple,用父类指针指向它时,属于upcast。

 

(1)      作业第二部分为Apple类重载::operator new 和 ::operator delete,并观察调用结果。

主程序如下:

intmain()

{

   Fruit my_fruit;

   cout <<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl;

   Apple my_apple;

   cout <<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl;

   Fruit* p = new Fruit();

   delete p;

   cout <<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl;

   Fruit* q = new Apple();

   delete q;

   cout <<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl;

   Apple* qq = new Apple[5];

   delete[] qq;

   cout <<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl;

   Fruit** wk = new Fruit*[5];

   for (int i = 0; i < 5; i++)

   {

            wk[i] = new Apple();

   }

   for (int i = 0; i < 5; i++)

   {

            delete wk[i];

   }

   delete wk;

   return 0;

}

 

头文件如下:

#ifndef__FRUIT__

#define__FRUIT__

#include<iostream>

usingnamespace std;

classFruit

{

   int no;

   double weight;

   char key;

public:

   Fruit() { cout << "The defaultFruit ctor.this= "

            << this << endl; }

   virtual ~Fruit() {

            cout << "The Fruitdtor.this= "

                     << this <<endl;

   }

   void print(){}

   virtual void process(){}

};

 

classApple :public Fruit

{

   int size;

   char type;

public:

   Apple(){cout<<"The default Applector.this= "

            << this << endl;}

   virtual ~Apple() {

            cout << "The Appledtor.this= "

                     << this <<endl;

   }

   void save(){}

   virtual void process(){}

   static void* operator new(size_t size);

   static void operator delete(void* ptr,size_tsize);

   static void* operator new[](size_t size);

   static void operator delete[](void*ptr,size_t size);

};

 

inline

void*Apple::operator new(size_t size)

{

   Apple* p = (Apple*)malloc(size);

   cout << "Apple::new()_size= "<< size << ", return:" << p << endl;

   return p;

}

 

inline

voidApple::operator delete(void* ptr, size_t size)

{

   cout << "Apple::delete()_size=" << size << ", ptr=" << ptr << endl;

   free(ptr);

}

 

inline

void*Apple::operator new[](size_t size)

{

   Apple* p = (Apple*)malloc(size);

   cout << "Apple::new[]()_size=" << size << ", return:" << p << endl;

   return p;

}

 

inline

voidApple::operator delete[](void* prt, size_t size)

{

   cout << "Apple::delete[]()_size=" << size << ", prt=" << prt << endl;

   free(prt);

}

#endif

 

 

编译结果如下:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值