zoukankan      html  css  js  c++  java
  • 父类中“this” 指向问题

         在程序的时候往往会看到在父类的一个函数中用到"this",我们知道this指向当前的这个对象,具体点就是当前运行中的对象,如果在父类中有虚函数,那么这个this调用的方法就可能是子类中的实现的虚函数。

          其实这些在我们学习this和继承的时候老师都会提到,而且老师会讲到内存结构,比如一构造一个子类的时候,会先构造父类,然后将父类的这个内存块作为子类内存块的一部分,比如说class C继承了class B,而B又继承了class a,那么C的内存结构可以看下面的图:

    也就是说子类的内存结构=父类的内存结构+子类特有的部分。如果使用了虚函数,我们知道虚函数在C++和C#中有很重要的角色,可以在运行时识别对象,有一个专业术语叫做RTTI.也因为这样,有了多态的说法,多态这个玩意在程序中很有用的,具体的我就不在这里空谈了。

      上面说了,在子类对象创建的时候,先创建父类对象,那么如果在父类的构造函数中出现了this,那情况如何,如果在父类的其他函数中出现this,这个我们都能想到,通过this调用的方法要么是父类的方法,要么是子类的实现了父类虚方法的方法(或者重写),可能比较拗口。那么父类的构造函数中的this情况如何?在这里我分别在C#和C++中模拟,发现C#中的这个this,会直接调用子类的实现父类的虚方法(或者重写),而C++中则是调用父类的方法,当构造函数结束后,调用的则是子类,让我自己去考虑的话,我觉得C++的才是正确的,因为在构造子类的时候先调用父类的构造函数,而这个时候子类还没有产生,所以出现在父类的构造函数中的this调用的方法应该是父类的,但是C#为什么不一样呢?这我不清楚,只能猜测,因为构造子类,调用父类,其实父类这个时候是作为子类内存的部分的,如果这样的话,好像也没错?我只能将这个归结为编译器的差异。

    这里我分别给出两种语言的代码,有兴趣的可以试试。

    C#代码:

    namespace ConsoleInherit
    {
        class Program
        {
            static void Main(string[] args)
            {
                int x = CFish.s;
                CFish pFish = new CFish();
    
                CAnimal pA = pFish;
    
                pA.eat();
    
                pA.yeep();
    
                Console.WriteLine();
            }
        }
    }
    
    
    namespace ConsoleInherit
    {
        public class CAnimal
        {
            CAnimal Ca;
    
           public  CAnimal()
            {
                Ca = this;
                Ca.yeep();//和C++ 不一样,这个this直接调用子类的虚函数
                Ca.eat();
                this.eat();
               
            }
            public void eat()
           {
                 Ca.yeep();
                Console.Write("Animal eat!");
    
            }
    
            public virtual void yeep()
            {
                Console.Write("Animal yepp!");
            }
        }
    }
    
    
    namespace ConsoleInherit
    {
        class CFish:CAnimal
        {
            public new void eat()
            {
    
                Console.Write("fish eat!");
    
            }
           public static int s;
            static void Get()
            {
                CFish pFish = new CFish();
            }
    
            public void swim()
            {
                Console.Write("fish swim!");
    
            }
    
            public override void yeep()
            {
                Console.Write("Fish yeep!");
            }
        }
    }
    
    
    

     C++的代码:

    #pragma once
    class CAnimal
    {
    	
    public:
    	CAnimal *Ca;
    	CAnimal(void);
    	~CAnimal(void);
    	void eat();
    	void breathe();
        virtual void yeep();
    
    };
    
    
    
    
    using namespace std;
    
    CAnimal::CAnimal(void)
    {
    	Ca=this;
    	Ca->yeep();//为什么是父类的?,难道是因为子类还没有实例化完?和C#中不一样
    	
    }
    
    
    CAnimal::~CAnimal(void)
    {
    }
    void CAnimal::eat()
    {   Ca->yeep();//这里调用的是子类的
    	cout<<"Animal eat"<<endl;
    }
    void CAnimal::breathe()
    {
    	cout<<"Animal breathe"<<endl;
    }
    void CAnimal::yeep()
    {
    	cout<<"Animal yeep"<<endl;
    }
    
    
    
    #pragma once
    #include "animal.h"
    class CFish:public CAnimal
    	  {
    		  public:
    			  CFish();
    			  ~CFish();
    			  void swim();
    			  void breathe();
    			  virtual void yeep();
    	  };
    
    
    
    
    
    using namespace std;
    
    
    CFish::CFish(void)
    {
    	//调用Ca=this;
    }
    
    
    CFish::~CFish(void)
    {
    }
    void CFish:: swim()
    {
    	cout<<"Fish swim"<<endl;
    	
    }
    void CFish::breathe()
    {
    	cout<<" Fish breathe"<<endl;
    
    }
    void CFish::yeep()
    {
    	cout<<" Fish yeep"<<endl;
    }
    
    
    
    CFish cFish;
    
    	cFish.eat();//继承父类的方法
    	cFish.swim();
    	//cFish.breathe();
    	CAnimal *Canimal;
    	
    	CAnimal pAx=(CAnimal)cFish;
    
    	pAx.eat();
    
    	Canimal=&cFish;
    
    	//Canimal->breathe();//重载是由指针类型决定,虚函数是由具体的对象决定
    
    	//Canimal->yep();
    	Canimal->Ca->yeep();
    	Canimal->Ca->breathe();//调用子类的虚函数
    	cout<<""<<endl;
    
    
    

     上面的只是自己的猜测,如果您有其他看法,欢迎交流!

  • 相关阅读:
    epoll精髓【epoll】
    linux下调试core的命令,察看堆栈状态命令 摘录(http://blog.csdn.net/yearn520/article/details/6663265)
    使用epoll 在 linux 上开发高性能应用服务器【epoll】
    linux下epoll如何实现高效处理百万句柄的[转]【epoll】
    log4cplus入门
    非阻塞式服务器和客户端程序(TCP)【简单的原理例子】
    Linux有用的命令记录
    在Linux上的使用开源C++日志库log4cplus
    静态库和动态库的区别
    localtime多线下不安全,localtime_r线程安全
  • 原文地址:https://www.cnblogs.com/zuiyirenjian/p/3059294.html
Copyright © 2011-2022 走看看