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