【C++ HJ高级-P12】虚函数与多态,继承与复合

本文深入探讨了面向对象编程中的函数分类,包括非虚拟函数、虚拟函数和纯虚拟函数的使用场景。通过示例解释了虚拟继承的概念,并展示了构造与析构函数在继承与复合关系下的调用顺序。关键点在于理解构造过程中的调用顺序:复合类 -> 父类 -> 子类。同时,文章提供了实例代码展示在堆栈和堆内存中创建对象时的不同行为。
摘要由CSDN通过智能技术生成

目录

0.引用

1.按照是否希望子类重写父类的函数将函数分类

2.一个简单的示例

3.Inheritance with virtual(带有virtual的继承)

3.1课件截图

3.2继承关系的例子

4.继承与复合关系下的构造与析构

4.1 课件

4.2 测试继承与复合关系的构造与析构

4.3 结论 


0.引用

子类和父类的构造函数的调用顺序

1.按照是否希望子类重写父类的函数将函数分类

1.non-virtual函数
你不希望子类(derived class)重新定义(override,复写);
2.virtual函数
你允许子类(derived class)重新定义(override,复写),且不对它已经有了默认定义,子类不定义也没有
关系;
3.pure virtual函数
你希望子类(derived class)一定要重新定义(override,复写),且你对他没有默认定义.


函数的继承继承不该从内存的角度去理解,函数继承的是调用权.

2.一个简单的示例

class Shape{
   public:
      virtual void draw() const = 0;// pure virtual
      virtual void error(const std::string& msg); // impure virtual
      int objectID() const; // non-virtual 
      ...
}

class Rectangle:public Shape{...};
class Ellipse:public Shape{...};

3.Inheritance with virtual(带有virtual的继承)

3.1课件截图

模板方法模式(Template Method)--是23个设计模式之一.
上图中理解的关键就在于那个被隐藏的this指针.


Application framework:
CDocument::OnFileOpen(){
   ...
   Serialize();
   ...
}

3.2继承关系的例子

include <iostream>
using namespace std;
class CDocument{
 public:
     void OnFileOpen(){
       cout << "diaglog..." << endl;
       cout << "check file status..."<< endl;
       cout << "open file ..."<< endl;
       Serialize();
       cout << "close file ..." << endl;
       cout << "update all views..." << endl;
     }   
     virtual void Serialize(){};
};
class CMyDoc:public CDocument{
  public:
     virtual void Serialize(){
      // 只有应用程序本身才知道如何读取自己的文件(格式)
      cout << "CMyDoc:: Serialize()"<< endl;
     }   
};
int main(){
     CMyDoc myDoc;
     myDoc.OnFileOpen();
     return 0;
}

4.继承与复合关系下的构造与析构

4.1 课件

4.2 测试继承与复合关系的构造与析构

情况1(虚拟机上的代码003.cpp):
#include <iostream> 
using namespace std;
class Component{
public:
      Component(){cout << "Component constructor" <<endl;}
      ~Component(){cout << "Component destructor" << endl;}
};

class Base{
public:
      Base(){cout << "Base constructor"<< endl;  }
      ~Base(){cout << "Base destructor"<< endl;  }
};
class Derived:public Base
{
public:
      Derived(){cout << "Derived constructor" << endl;}
      ~Derived(){cout << "Derived destructot" << endl;}
      Component m_component;
};

int main(){
     cout << "=================  stack memory  ========================="<< endl;
     {
       Derived obj_derived1;
     }
     cout << "=================  heap  memory  ========================="<< endl;
     Derived* obj_derived2 = new Derived;
     delete obj_derived2;
}


执行结果:
=================  stack memory  =========================
Base constructor
Component constructor
Derived constructor
Derived destructot
Component destructor
Base destructor
=================  heap  memory  =========================
Base constructor
Component constructor
Derived constructor
Derived destructot
Component destructor
Base destructor




情况2(虚拟机上的代码002.cpp):
#include <iostream> 
using namespace std;
class Component{
public:
      Component(){cout << "Component constructor" <<endl;}
      ~Component(){cout << "Component destructor" << endl;}
};

class Base{
public:
      Base(){cout << "Base constructor"<< endl;  }
      ~Base(){cout << "Base destructor"<< endl;  }
      Component m_component;
};
class Derived:public Base
{
public:
      Derived(){cout << "Derived constructor" << endl;}
      ~Derived(){cout << "Derived destructot" << endl;}
};

int main(){
     cout << "=================  stack memory  ========================="<< endl;
     {
       Derived obj_derived1;
     }
     cout << "=================  heap  memory  ========================="<< endl;
     Derived* obj_derived2 = new Derived;
     delete obj_derived2;
}

执行结果:
=================  stack memory  =========================
Component constructor
Base constructor
Derived constructor
Derived destructot
Base destructor
Component destructor
=================  heap  memory  =========================
Component constructor
Base constructor
Derived constructor
Derived destructot
Base destructor
Component destructor


4.3 结论 

对于以上给出的简单的例子,可以看出,创建一个子类的对象的时候,
当父类中有复合类对象的时候,其构造顺序:
复合类-->父类-->子类;
当子类中有复合类的对象的时候,其构造顺序是:
父类-->复合类-->子类.

如果有更复杂的情况,还需要再分析,以上仅仅对4.2中的例子gcc下有效.

在子类构造的时候,如果同时有复合关系和继承关系,在调用构造函数的时候,
继承关系优先于复合关系被调用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值