class CA
{
public:
virtual void fun1()
{
cout<<"CA::fun1()"<<endl;
}
void fun2()
{
fun1();
cout<<"CA::fun2()"<<endl;
}
};
class CB:public CA
{
public:
virtual void fun1()
{
cout<<"CB::fun1()"<<endl;
}
void fun2()
{
fun1();
cout<<"CB::fun2()"<<endl;
}
};
void main()
{
CA *p =new CB();
p->fun1();
p->fun2();
}
上面代码输出是什么?有什么bug?如何解决?
我的回答是:因为CA中fun2不是虚函数,而CA *p =new CB()时会进行类型转换,所以输出的结果是
CB::fun1()
CA::fun1()
CA::fun2()
后面被面试官问的很狼狈啊,他的问题大概是:有什么bug,是编译过程、链接过程还是运行过程中会出现问题?
回来后自己运行了下程序,得到的结果是
CB::fun1
CB::fun1
CA::fun2
忘高手详细分析,谢谢
12 个解决方案
#1
调试一遍,看看整个执行过程。
#2
这题我做过,在北京的一家公司。
我当时写的是
delete p;
p = 0;
我后来没被问到笔试题。
这道题应该是笔试的时候做的吧,面试的时候拿着笔试的题问的吗?
我惊异的是楼主能过目不忘?
我当时写的是
delete p;
p = 0;
我后来没被问到笔试题。
这道题应该是笔试的时候做的吧,面试的时候拿着笔试的题问的吗?
我惊异的是楼主能过目不忘?
#3
第二行输出就是到底调用哪个fun1,由于fun1是虚函数,调用时是由虚函数表中的函数地址决定的,由于
CA *p =new CB();中,虽然p是CA指针,但是他指向的虚函数表是CB的虚函数表(多态),所以调用的虚函数是CB中的虚函数,故第二行打引
CB::fun1
CA *p =new CB();中,虽然p是CA指针,但是他指向的虚函数表是CB的虚函数表(多态),所以调用的虚函数是CB中的虚函数,故第二行打引
CB::fun1
#4
CB::fun1 还是 CA::fun1 这个地方,其实换句话说,就是问虚函数与重载函数的区别。区别就在这里
#5
呵呵 这题目问的我很纠结啊,印象深刻啊!
#6
嗯 p指向CB中的虚函数表,然后查找虚函数表,fun1存在所以调用的是CB::fun1。
所以最终结果为:
CB::fun1
CB::fun1
CA::fun2
但是这段代码有bug吗?还请指点.
#7
只要是virtual函数调用, 就一定通过this的 虚函数指针 指向 的 虚函数表 去查找.
#8
++
#9
bug? 有什么bug?
virtual ~CA() ?
delete p?
try{CA* p = new CB();}?
virtual ~CA() ?
delete p?
try{CA* p = new CB();}?
#10
完整的代码是这样的:
#include<iostream>
using namespace std;
class CA
{
public:
virtual void fun1()
{
cout<<"CA::fun1()"<<endl;
}
void fun2()
{
fun1();
cout<<"CA::fun2()"<<endl;
}
};
class CB:public CA
{
public:
CB()
{
p=new int[20];
};
~CB()
{
delete p;
}
virtual void fun1()
{
cout<<"CB::fun1()"<<endl;
}
void fun2()
{
fun1();
cout<<"CB::fun2()"<<endl;
}
private:
int *p;
};
void main()
{
CA *p =new CB();
p->fun1();
p->fun2();
}
应该和virtual ~CA() ? ;delete p?这些没关系。
#11
。。。怎么都是继承的不行,
楼主速度回去补习两编C++permier
当子类有基类的同名成员,但是却不是虚函数的时候基类的同名函数会被覆盖掉(这个是Link错误,或编译错误)这个时候函数调用更具静态类型(就是编译时候的类型)
还有。。那个fun2里不是又调用了一次fun1嘛,只要fun1是虚函数,在子类里无论怎么调用,
都应该是用子类定义的函数
楼主速度回去补习两编C++permier
当子类有基类的同名成员,但是却不是虚函数的时候基类的同名函数会被覆盖掉(这个是Link错误,或编译错误)这个时候函数调用更具静态类型(就是编译时候的类型)
还有。。那个fun2里不是又调用了一次fun1嘛,只要fun1是虚函数,在子类里无论怎么调用,
都应该是用子类定义的函数
#12
表示布吉岛!
#1
调试一遍,看看整个执行过程。
#2
这题我做过,在北京的一家公司。
我当时写的是
delete p;
p = 0;
我后来没被问到笔试题。
这道题应该是笔试的时候做的吧,面试的时候拿着笔试的题问的吗?
我惊异的是楼主能过目不忘?
我当时写的是
delete p;
p = 0;
我后来没被问到笔试题。
这道题应该是笔试的时候做的吧,面试的时候拿着笔试的题问的吗?
我惊异的是楼主能过目不忘?
#3
第二行输出就是到底调用哪个fun1,由于fun1是虚函数,调用时是由虚函数表中的函数地址决定的,由于
CA *p =new CB();中,虽然p是CA指针,但是他指向的虚函数表是CB的虚函数表(多态),所以调用的虚函数是CB中的虚函数,故第二行打引
CB::fun1
CA *p =new CB();中,虽然p是CA指针,但是他指向的虚函数表是CB的虚函数表(多态),所以调用的虚函数是CB中的虚函数,故第二行打引
CB::fun1
#4
CB::fun1 还是 CA::fun1 这个地方,其实换句话说,就是问虚函数与重载函数的区别。区别就在这里
#5
呵呵 这题目问的我很纠结啊,印象深刻啊!
#6
嗯 p指向CB中的虚函数表,然后查找虚函数表,fun1存在所以调用的是CB::fun1。
所以最终结果为:
CB::fun1
CB::fun1
CA::fun2
但是这段代码有bug吗?还请指点.
#7
只要是virtual函数调用, 就一定通过this的 虚函数指针 指向 的 虚函数表 去查找.
#8
++
#9
bug? 有什么bug?
virtual ~CA() ?
delete p?
try{CA* p = new CB();}?
virtual ~CA() ?
delete p?
try{CA* p = new CB();}?
#10
完整的代码是这样的:
#include<iostream>
using namespace std;
class CA
{
public:
virtual void fun1()
{
cout<<"CA::fun1()"<<endl;
}
void fun2()
{
fun1();
cout<<"CA::fun2()"<<endl;
}
};
class CB:public CA
{
public:
CB()
{
p=new int[20];
};
~CB()
{
delete p;
}
virtual void fun1()
{
cout<<"CB::fun1()"<<endl;
}
void fun2()
{
fun1();
cout<<"CB::fun2()"<<endl;
}
private:
int *p;
};
void main()
{
CA *p =new CB();
p->fun1();
p->fun2();
}
应该和virtual ~CA() ? ;delete p?这些没关系。
#11
。。。怎么都是继承的不行,
楼主速度回去补习两编C++permier
当子类有基类的同名成员,但是却不是虚函数的时候基类的同名函数会被覆盖掉(这个是Link错误,或编译错误)这个时候函数调用更具静态类型(就是编译时候的类型)
还有。。那个fun2里不是又调用了一次fun1嘛,只要fun1是虚函数,在子类里无论怎么调用,
都应该是用子类定义的函数
楼主速度回去补习两编C++permier
当子类有基类的同名成员,但是却不是虚函数的时候基类的同名函数会被覆盖掉(这个是Link错误,或编译错误)这个时候函数调用更具静态类型(就是编译时候的类型)
还有。。那个fun2里不是又调用了一次fun1嘛,只要fun1是虚函数,在子类里无论怎么调用,
都应该是用子类定义的函数
#12
表示布吉岛!