在程序的时候往往会看到在父类的一个函数中用到"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;

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

父类中“this” 指向问题相关推荐

  1. c++纯虚函数在父类中调用的规避

    构造和析构函数不允许调用纯虚函数,可以先调用虚函数,里面再调用纯虚函数实现. class Base{ public:     virtual void foo()=0;     Base() { ca ...

  2. ES6/03/函数的定义方式和调用方式,函数内的this指向,改变函数中this指向的三个方法(call(),apply(),bind())

    函数的定义方式 1,自定义函数(命名函数) function fun(){}; 2,函数表达式(匿名函数) var fun =function(){}; 3,利用new Function( '参数1' ...

  3. 父类指针可以指向子类对象

    结论:父类指针可以指向子类对象,但是只能访问父类成员,不能访问子类成员 结论:子类指针不可以指向父类对象,需要类型转换才可以 笔记: <1>.当基类指针指向派生类的时候,只能操作派生类从基 ...

  4. 父类的对象指向子类对象,父类可以调用子类的方法吗?

    例如父类Person指向子类Student: Person p = new Student(); 父类类型实例p可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,它是无可奈何的: ...

  5. java 子类调用静态方法吗_Java子父类中静态方法

    Java中的静态方法只能继承,不能重写!! 官方文档是这样写的: Class methods If a subclass defines a class method with the same si ...

  6. 父类的引用指向子类的对象

    最近有所感悟,写一下最多态新的理解吧: 父类引用指向子类对象指的是: 例如父类Animal,子类Cat,Dog.其中Animal可以是类也可以是接口,Cat和Dog是继承或实现Animal的子类. A ...

  7. idea中设置指向源代码Scala

    1.到官网下载scala源代码 点击如下链接下载源码:http://www.scala-lang.org/download/all.html 选择需要的版本点击进行下载,我选择的是2.11.8版本,如 ...

  8. php父类的静态变量,抽象父类中的PHP静态变量:问题是在示例代码中!

    问题的快速代码包括: abstract class ClassParent { public static $var1 = "ClassParent"; } class Class ...

  9. 【面向对象编程】(4) 类的继承,重构父类中的方法

    各位同学好,今天和大家分享一下面向对象编程中,类的三大特征之继承.主要介绍:子类继承父类的基本方法:重写父类的类方法:重构父类的初始化方法:super() 方法.本节主要是单继承,多继承在下一节中介绍 ...

最新文章

  1. burp suite java_Burpsuite插件自动二手开发
  2. Dell R410/710 升级网卡驱动
  3. Redis中的可用性保证之Sentinel服务下线
  4. SlickOne 敏捷开发框架介绍(二) -- 多用户/多租户/SAAS软件基础框架实现
  5. mysql数值类型总结及常用函数
  6. s:iterator标签的使用
  7. 【转】聊聊分布式事务,再说说解决方案
  8. ios 时间戳 当前时间 相互转化
  9. [转载] python猜字谜游戏_Python Hangman猜字游戏
  10. VS添加lib库文件步骤
  11. 计算经纬度、距离、方位角
  12. DigitalFilmTools Rays 2.1.2汉化版|丁达尔光束耶稣光滤镜插件
  13. 蓝牙的原理,蓝牙耳机怎么连接手机
  14. opencv 颜色识别
  15. 更上一层楼,数学是基础——渐近线和可分离变量微分方程
  16. 【Python教程】python语言风格
  17. obd 与服务器通讯协议,OBD系统的通讯协议介绍 - 〖汽车维修设备制作〗 - 中威汽车电子技术论坛 - Powered by Discuz!...
  18. Chrome浏览器的自带翻译用途
  19. java反射 interface_Java反射
  20. MA、WMA、EMA、EXPMA区别及公式详述

热门文章

  1. 荣耀手表magic2更新鸿蒙时间表,荣耀手表2更新百种运动模式 618期间到手价799元起...
  2. Swift - 使用 Protocol 避免框架之间循环引用
  3. SQL Server 2017 AlwaysOn on Linux 配置和维护(18)
  4. 2018-03-02 Linux
  5. vue更新数组和对象
  6. gRPC异步处理应答
  7. iOS之HTTP和HTTPS的基本知识和应用
  8. php 之 数据访问 增删改查
  9. iOS开发-关于自定义控件很值得一看的文章(一)
  10. 打造精简版Linux-mini