weitom1982

向各位技术前辈学习,学习再学习.
posts - 299, comments - 79, trackbacks - 0, articles - 0
  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
虚函数地址的找法:

#include "stdafx.h"
#include 
<iostream>
using namespace std;
class CBase
{
public:
    
virtual void who(){cout<<"CBase"<<endl;}
}
;
class CDerived:public CBase
{
public:
    
virtual void who(){cout<<"CDerived"<<endl;}
}
;
int _tmain(int argc, _TCHAR* argv[])
{
    
long num1=0;
    
long num2=0;
    CBase 
*base=new CBase;//必须用new后,才可以找到
    CDerived *derived=new CDerived;
    num1
=*(long*)(*(long*)base);//找到第一个虚函数的地址
    num2=*(long*)(*(long*)derived);
    cout
<<num1<<endl;
    cout
<<num2<<endl;
    
return 0;
}


#include "stdafx.h"
#include <iostream>
using namespace std;
class CBase
{
public:
 virtual void who(){cout<<"CBase"<<endl;}
};
class CDerived:public CBase
{
public:
 virtual void who(){cout<<"CDerived"<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
 long num1=0;
 long num2=0;
 CBase *base=new CBase;//必须用new后,才可以找到
 CDerived *derived=new CDerived;
 num1=*(long*)(*(long*)base);//找到第一个虚函数的地址
 num2=*(long*)(*(long*)derived);
 cout<<num1<<endl;
 cout<<num2<<endl;
 return 0;
}

---------------------------------------
虚函数的定义要遵循以下重要规则:

  1.如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,那么即使加上了virtual关键字,也是不会进行滞后

联编的。

  2.只有类的成员函数才能说明为虚函数,因为虚函数仅适合用与有继承关系的类对象,所以普通函数不能说明为虚函数。

  3.静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象。

  4.内联(inline)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚函数在类的内部定义定义,但是在编译的时候系统仍然将它看做是非内联的。

  5.构造函数不能是虚函数,因为构造的时候,对象还是一片位定型的空间,只有构造完成后,对象才是具体类的实例。

  6.析构函数可以是虚函数,而且通常声名为虚函数。
------------------------------------

1)Derived:public Base

  
        CBase  pBase;
 CDerived pDerived;
 CBase *pBase2= new CDerived;
        delete pBase2;
 CDerived pDerived2;

                //results:             
         //CBase::CBase               // CBase  pBase;
  //CBase::CBase               //CDerived pDerived;
  //CDerived:: CDerived
  //CBase::CBase               //CBase *pBase2= new CDerived;
  //CDerived:: CDerived
  //CBase::~CBase              // delete pBase2;//因为基类的析构不是虚,如                                                                是则先调用子类的析构
  //CBase::CBase               //CDerived pDerived2;
  //CDerived:: CDerived       
  //CDerived::~CDerived         //CDerived pDerived2;   
  //CBase::~CBase
  //CDerived::~CDerived         //CDerived pDerived;  
  //CBase::~CBase
  //CBase::~CBase               //CBase  pBase;    
  //Press any key to continue


     如果是子类构造先基类,再子类
     如果是子类析构先子类,再基类
     但如果基类析构不是虚,则CBase *pBase2= new CDerived;
             delete pBase2;只调用基类.否则如果基类析构是虚,则先调用子类,再调用基类。
     如果是用new初始化的,必须用delete来释放,否则不调用析构函数。

     CDerived pDerived(10);//the base class must be have the defaut constructor


//CBase::CBase
//this is defuat  constructor function
//CDerived:: CDerived
//CDerived::~CDerived
//CBase::~CBase
//CBase::~CBase
//Press any key to continue


如果子类中有基类的对象成员,则先调用基类的构造函数,再调用基类的构造函数对基类的对象成员初始化,最后才调用子类的构造函数,析构正好顺序相反。

 


2)CBase1:public  CBase
  CBase2:public  CBase
  CDervied:public  CBase1,CBase2

CDerived  pdereved;

如果没有定义为虚继承 ,先调用基类再子类然后再基类再子类最后才调用子子类构造。
CBase::CBase()!
CBase1::CBase()!
CBase::CBase()!
CBase2::CBase()!
CDerived::CDerived()!
CDerived::~CDerived()!
CBase2::~CBase()!
CBase::~CBase()!
CBase1::~CBase()!
CBase::~CBase()!
Press any key to continue

如果cbase1与cbase2是虚继承cbase,则只调用一次基类
CBase::CBase()!
CBase1::CBase()!
CBase2::CBase()!
CDerived::CDerived()!
CDerived::~CDerived()!
CBase2::~CBase()!
CBase1::~CBase()!
CBase::~CBase()!
Press any key to continue

-----------------------------------
多重继承的成员调用:


  cbase
  CBase1:public  CBase
  CBase2:public  CBase
  CDervied:public  CBase1,CBase2
1)当cbase1与cbase2不是虚继承的时:dervied不能访问基类继承而来(即共有的)的任何成员,不能识别。

2)当cbase1与cbase2是虚继承的时,dervied可以访问cbase中没有1和2重新定义的成员,也能访问只被1或只被2重新定义的成员,这是调用1或2中的成员,当dervied中有重写时,调用derived中重新定义的成员。(共有)

:保证我们在不考虑继承而来的隐藏成员时,能够识别该调用那个类中的!则编译器也能识别!
3)
在调用变量的时候,要指出时属于那个类。

只有注册用户登录后才能发表评论。