网上找的阿里的一个面试题

struct A {
	void fun1() {
		cout << "1";
	}
};

struct B : public A {
	void fun2(A * a) {
		cout << "2";
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	A a;
	B * b = static_cast<B*>(&a);
	b->fun2(&a);
	b->fun1();
	cout << 3 << endl;
}

输出为 213.

解释:static_cast类似于强制类型转换,成员函数不是存储在类对象中,而是在程序只有一份,存在于代码段中。通过B类的指针去代码段中查找B类对应的成员函数,显然是能够正确运行的。fun1在B类的基类中,查找到fun1也是没有问题的。因此此题编译/运行都没有错误,输出213.


struct A
{ 
    void fun1() 
    {
        cout <<"1";
    } 
}; 
struct B:public A
{ 
    void fun2(A *a) 
    {
        cout <<"2";
    } 
};
void main() 
{ 
    A a; 
    B *b=dynamic_cast <B*>(&a); 
    b->fun2(&a); 
    cout <<3 <<endl; 
} 
 
编译时错误,因为dynamic_cast只能用在有虚函数的类中,所以此代码不能编译通过。

struct A {
	virtual void fun1() {
		cout << "1";
	}
};

struct B : public A {
	virtual void fun2(A * a) {
		cout << "2";
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	A a;
	B * b = static_cast<B*>(&a);
	b->fun2(&a);   //test1
	//b->fun1();   //test2
	cout << 3 << endl;
运行时错误。
原因:A和B都带有需函数,因此都有vptr指针指向各自的虚函数表。a对象的虚函数指针指向A类的虚函数表,而A类没有fun2。强制转换成B类之后,其实vptr还是指向A类的虚函数表,那么b->fun2在运行时刻找不到从而运行出错。
如果把main中带有//test1的行注释掉,把//test2的行给打开,那么运行是没有问题的,输出13.
原因是:给予上面的分析,虽然转换成了B的指针,但是vptr仍然指向A的虚函数表,自然b->fun1是可以找到的,并且运行正确。

struct A {
	virtual void fun1() {
		cout << "1";
	}
};

struct B : public A {
	virtual void fun2(A * a) {
		cout << "2";
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	A a;
	B * b = dynamic_cast<B*>(&a);
	if (b == NULL){
		cout << "b is NULL" << endl;
		return 0;
	}

	b->fun2(&a);
	//b->fun1();
	cout << 3 << endl;
输出 b is NULL.
转换失败。

static_cast:
    在编译期间进行转换。
    对于类只能在继承体系之中的类之间互转。
dynamic_cast:
    1.把派生类指针或者引用转换成基类的指针或者引用可以不用dynamic_cast,也可以使用dynamic_cast,使用就像不使用时一样。
       派生类转换成基类,则不需要派生类或者基类中有虚函数。
    2.把基类转换成派生类,要求基类中要有虚函数(即是多态类类型)。
       dynamic_Cast会检查转换是否有效,也就是说转换会检查是否会返回一个有效的被请求的有效的完整对象(目的类的对象)。检测在运行时进行。
       如果被转换的指针不是一个有效的被请求的完整对象(目的类的对象),则返回NULL。
       当待转换指针或目标指针式void *时,dynamic_cast总认为是安全的。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值