网上看到一面试,小小试了下,小小研究下。
根据代码,判断打印结果。
#pragma once
#include "stdio.h"
class CA
{
public:
CA(void);
~CA(void);
public:
virtual int fun()
{
i = 1;
return 0;
};
int print()
{
printf("%d\n",i);
return 0;
}
private:
int i;
};
#pragma once
#include "a.h"
class CB :
public CA
{
public:
CB(void);
~CB(void);
public:
virtual int fun()
{
i = 2;
return 0;
};
void print()
{
printf("%d\n",i);
};
private:
int i;
};
#pragma once
#include "b.h"
class CC :
public CB
{
public:
CC(void);
~CC(void);
public:
virtual int fun()
{
i = 3;
return 0;
};
int print()
{
printf("%d\n",i);
return 0;
};
private:
int i;
};
//test sun class point value.
#include "A.h"
#include "B.h"
#include "C.h"
int main()
{
//new 子类的,A.i= 2,调用子类的函数,print不是虚函数,所以,还是父类的print,值不对
CA *A = new CB();
(A)->fun();
A->print();
//new 父类,必须强制转换才可以编译通过。fun 调用的还是父类的,B.i = 1; print 不是虚函数,还是调用的CC的,值不对。
CC *B =(CC*) new CA;
B->fun();
B->print();
CC *C = (CC *)new CB;
C->fun();
C->print();
CC c;
c.fun();
c.print();
}
解释下,父类指针new(实例化) 子类,是合乎常理的,在指针调用函数时,如何函数时虚函数,就会根据虚函数表,向下映射到子类,这是无容置疑的。因此,第一A.i = 1,但是print结果不正确,上面注释已经解释啦。不多说。
1)但是,如果子类指针new 成父类,如果没有(CC*)转换,是编译通不过的。必须强制转换一下。
2)如果这样使用 C方式这种强制转换后,编译没有任何问题,但是隐藏了个大问题,可能programer原意是想获得子类函数,但是 实际上,虚函数依然是父类fun(),而自己的函数还是自己的print()
所以,通常在使用类型转换的时候,使用dynamic_cast进行转换的话,运行时检查类型,就会crush掉。
CC *B =dynamic_cast<CC*>(new CA);
B->fun();
B->print();
这个会crush
简而言之,父类实例化子类,并使用dynamic_cast进行类型转换。