搞懂C++的虚拟继承(升级)

​   

作者:良知犹存

转载授权以及围观->欢迎添加Wx:Allen-Iverson-me-LYN

前言:本文为C++使用过程中的一些细节知识补充,碎片化的知识.其中有韦东山老师和其他博主一些知识笔记,在此谢谢韦老师以及各博主的文章博客,受益良多.

    多重定义会使程序进行基类调用,用virtual定义基类的程序函数,然后派生类(子类)进行虚拟函数继承调用,调用的时候内存占用以及编译执行情况是如何呢?          

  

联编机制:联编是指一个程序自身彼此关联的一个过程,按照联编所进行的阶段不同分为静态联编和动态联编.

1.静态联编,对于一般类的成员函数(非虚函数),在编译的时候就确定好了调用哪一个。而编译时所进行的联编又称为静态束定(束定是指确定所调用的函数与执行该函数代码之间的关系).

2.动态联编,在运行过程中解决选择调用函数与执行该函数代码之间的关系,又被成为动态束定。具体为:有一个指针,指向一个虚函数表;在调用的时候通过指针找到表,调用虚函数,进而将虚函数连接到当前类下。所以试下动态联编首先要有继承性,并且要求建立子类型关系,其次,一个重要条件是虚函数,继承是动态联编的基础,虚函数是动态联编的关键.

 普通继承:静态联编

虚拟继承:动态联编

     

    一般函数名字相同返回值不同的时候只能做重载不能进行虚拟函数,但是如果返回值是本次定义的类的指针或者引用时,虚拟函数才成立。

     虚拟析构函数,将析构函数定义为虚函数,但是需要注意,如果我们派生类分配了内存空间.但是基类的析构函数不是虚析构函数的情况下,类执行析构函数的时候只执行基类析构函数,派生类则没有,造成内存泄漏.

class D{......};class B: public D{......};int main(int argc, char **argv){    D* d = new b;    return 0;}

using namespace std;class Human {private:  int a;public:  virtual void eating(void) { cout<<"use hand to eat"<<endl; }  virtual ~Human() { cout<<"~Human()"<<endl; }    virtual Human* test(void) {         cout<<"Englishman test()"<<endl;         return this;        }};class Englishman : public Human {public:  void eating(void) { cout<<"use knife to eat"<<endl; }  virtual ~Englishman() { cout<<"~Englishman()"<<endl; }    virtual Englishman* test(void) {         cout<<"Englishman test()"<<endl;         return this;        }};class Chinese : public Human {public:  void eating(void) { cout<<"use chopsticks to eat"<<endl; }  virtual ~Chinese() { cout<<"~Chinese()"<<endl; }/*析构函数也应该为虚拟函数*/    virtual Chinese* test(void) {         cout<<"Chinese test()"<<endl;         return this;        }};void test_eating(Human h){  h.eating();}void test_return(Human h){  h.test();}int main(int argc, char **argv){    Human h;    Englishman e;    Chinese c;    test_return(h);    test_return(e);    test_return(c);  return 0;}

      动态类型转化中经常使用指针,一般不适用引用,因为引用在被转换判断的时候,实体可能不存在,引用指向也就没有意义,程序就会执行失败。

/*类的定义和上面范例定义相同,此处就不多做赘述*/void test_eating(Human &h){    #if 0/*有隐患*/    Englishman &pe = reinterpret_cast<Englishman&>(h);/*静态显性强制转化*/    Chinese    &pc = reinterpret_cast<Chinese&>(h);    Guangximan &pg = reinterpret_cast<Guangximan&>(h);        #else    // Englishman &pe = dynamic_cast<Englishman&>(h);/*error*/    Chinese    &pc = dynamic_cast<Chinese&>(h); /*动态转换*/    Guangximan &pg = dynamic_cast<Guangximan&>(h);    #endif  h.eating();    /*想分辨哪个国家的人*/}void test_return(Human h){  h.test();}int main(int argc, char **argv){    Human h;    Guangximan g;    Englishman *pe;    pe = static_cast<Englishman*>(&h);    // Englishman *pe2 = static_cast<Englishman*>(&g);    Chinese *pc = static_cast<Chinese*>(&g);    test_eating(g);  return 0;}

     

      类与派生类之间:函数名相同,参数与返回值也同样相同的函数叫做覆写函数,函数名相同参数不同叫做重载函数。

    覆写函数通常应用于子类继承父类时,重写父类中的函数,覆写的函数不能在父类中为private,否则只是相当于在子类中新写了一个函数.

        C++允许在同一作用域中的某个函数和运算符指定多个定义,分别成为重载函数和重载运算符.

namespace C{ using namespace std;class Point{private:    int x;    int y;    public:    Point()    {        std::cout << "/* Point() */" << std::endl;    }    Point(int x,int y) : x(x),y(y)    {        std::cout << "/* Point(int x,int y) */" << std::endl;    }    Point(const Point& p)    {        std::cout << "Point(const Point& p)" << std::endl;        x = p.x;        y = p.y;    }        ~Point()    {        std::cout << "/* ~Point() */" << std::endl;    }        int getX(){return x;}    int getY(){return y;}    int setX(int x){this->x = x;}    int setY(int y){this->y = y;}    void printInfo(){        cout<<"("<<x<<","<<y<<")"<<endl;    }    friend Point add(Point &p1,Point &p2);    friend Point operator+(Point &p1,Point &p2);    friend Point operator++(Point &p,int a);    friend Point operator++(Point &p);};Point add(Point &p1,Point &p2){     Point  n ;    n.x=(p1.x+p2.x);        n.y=(p1.y+p2.y);    return n ;}Point operator+(Point &p1,Point &p2){    cout<<"Point operator+(Point &p1,Point &p2)"<<endl;    Point  n ;    n.x=(p1.x+p2.x);        n.y=(p1.y+p2.y);    return n ;}/*Point p(1,2); ++p 函数重载 通过参数的不一致进行区分*/Point operator++(Point &p){    std::cout << "++p" << std::endl;    p.x += 1;    p.y += 1;    return p;}/*Point p(1,2); p++ */Point operator++(Point &p,int a){    std::cout << "p++" << std::endl;    Point n;    n = p;    p.x += 1;    p.y += 1;    return n;    }}#include "point.h"using namespace C;int Person::cnt = 0; /*定义和初始化 此处并不是全局变量*/int main(int argc,char** argv){    Point p1(1,2);    Point p2(2,3);       std::cout << "begin" << std::endl;    ++p1;    p1.printInfo();    std::cout << "***********" << std::endl;    p2++;    p2.printInfo();        std::cout << "end" << std::endl;   return 0;}

                                                                  ————————END————————

                                                                              长按关注,你会得到更多信息.

猜你喜欢

转载自blog.csdn.net/lyn631579741/article/details/105477008