c++中普通函数调用虚函数问题

时间:2022-09-09 18:48:08
今天去面试了,受打击鸟,下面是面试的一道题目(大概),不是很懂,忘解答....
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;
我后来没被问到笔试题。
这道题应该是笔试的时候做的吧,面试的时候拿着笔试的题问的吗?
我惊异的是楼主能过目不忘?

#3


第二行输出就是到底调用哪个fun1,由于fun1是虚函数,调用时是由虚函数表中的函数地址决定的,由于
CA *p =new CB();中,虽然p是CA指针,但是他指向的虚函数表是CB的虚函数表(多态),所以调用的虚函数是CB中的虚函数,故第二行打引
CB::fun1

#4


CB::fun1 还是 CA::fun1 这个地方,其实换句话说,就是问虚函数与重载函数的区别。区别就在这里

#5


引用 2 楼  的回复:
这题我做过,在北京的一家公司。
我当时写的是
delete p;
p = 0;
我后来没被问到笔试题。
这道题应该是笔试的时候做的吧,面试的时候拿着笔试的题问的吗?
我惊异的是楼主能过目不忘?

呵呵 这题目问的我很纠结啊,印象深刻啊!

#6


引用 3 楼  的回复:
第二行输出就是到底调用哪个fun1,由于fun1是虚函数,调用时是由虚函数表中的函数地址决定的,由于
CA *p =new CB();中,虽然p是CA指针,但是他指向的虚函数表是CB的虚函数表(多态),所以调用的虚函数是CB中的虚函数,故第二行打引
CB::fun1


嗯 p指向CB中的虚函数表,然后查找虚函数表,fun1存在所以调用的是CB::fun1。
所以最终结果为:
CB::fun1
CB::fun1
CA::fun2
但是这段代码有bug吗?还请指点.

#7


只要是virtual函数调用, 就一定通过this的 虚函数指针 指向 的 虚函数表 去查找.

#8


引用 4 楼  的回复:
CB::fun1 还是 CA::fun1 这个地方,其实换句话说,就是问虚函数与重载函数的区别。区别就在这里


++

#9


bug? 有什么bug?
virtual ~CA() ?
delete p?
try{CA* p = new CB();}?

#10


引用 9 楼  的回复:
bug? 有什么bug?
virtual ~CA() ?
delete p?
try{CA* p = new CB();}?

完整的代码是这样的:
#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是虚函数,在子类里无论怎么调用,
都应该是用子类定义的函数

#12


表示布吉岛!

#1


调试一遍,看看整个执行过程。

#2


这题我做过,在北京的一家公司。
我当时写的是
delete p;
p = 0;
我后来没被问到笔试题。
这道题应该是笔试的时候做的吧,面试的时候拿着笔试的题问的吗?
我惊异的是楼主能过目不忘?

#3


第二行输出就是到底调用哪个fun1,由于fun1是虚函数,调用时是由虚函数表中的函数地址决定的,由于
CA *p =new CB();中,虽然p是CA指针,但是他指向的虚函数表是CB的虚函数表(多态),所以调用的虚函数是CB中的虚函数,故第二行打引
CB::fun1

#4


CB::fun1 还是 CA::fun1 这个地方,其实换句话说,就是问虚函数与重载函数的区别。区别就在这里

#5


引用 2 楼  的回复:
这题我做过,在北京的一家公司。
我当时写的是
delete p;
p = 0;
我后来没被问到笔试题。
这道题应该是笔试的时候做的吧,面试的时候拿着笔试的题问的吗?
我惊异的是楼主能过目不忘?

呵呵 这题目问的我很纠结啊,印象深刻啊!

#6


引用 3 楼  的回复:
第二行输出就是到底调用哪个fun1,由于fun1是虚函数,调用时是由虚函数表中的函数地址决定的,由于
CA *p =new CB();中,虽然p是CA指针,但是他指向的虚函数表是CB的虚函数表(多态),所以调用的虚函数是CB中的虚函数,故第二行打引
CB::fun1


嗯 p指向CB中的虚函数表,然后查找虚函数表,fun1存在所以调用的是CB::fun1。
所以最终结果为:
CB::fun1
CB::fun1
CA::fun2
但是这段代码有bug吗?还请指点.

#7


只要是virtual函数调用, 就一定通过this的 虚函数指针 指向 的 虚函数表 去查找.

#8


引用 4 楼  的回复:
CB::fun1 还是 CA::fun1 这个地方,其实换句话说,就是问虚函数与重载函数的区别。区别就在这里


++

#9


bug? 有什么bug?
virtual ~CA() ?
delete p?
try{CA* p = new CB();}?

#10


引用 9 楼  的回复:
bug? 有什么bug?
virtual ~CA() ?
delete p?
try{CA* p = new CB();}?

完整的代码是这样的:
#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是虚函数,在子类里无论怎么调用,
都应该是用子类定义的函数

#12


表示布吉岛!