有虚函数时,每个对象的this指针都指向一个虚函数表(Virtual Table)的地址,这个表里存的就是虚函数的地址。编译的时候就决定了,普通函数调用时直接CALL这个函数的地址,而是虚函数时,是从这个虚表里取地址去调用的。
可以的,但是你这样的用法不对,a bbb只是声明了一个类型为a的指针,它没有所指的空间,如果之间调用bbb->fn1(2),会提示你没有初始化,这么用实际是没有意义的。可以这样:a bbb=new a,然后就可以了。
还有你cout<<"bbb"<<endl;是想干吗,貌似没什么意义。
#include <string>
#include <iostream>
using namespace std;
class A {
public:
virtual ~A() {};
};
class B: public A {};
class C: public B {};
string verify(A p)
{
if(dynamic_cast<C>(p)!=NULL)
return "son";
else if(dynamic_cast<B>(p)!=NULL)
return "father";
else if(dynamic_cast<A>(p)!=NULL)
return "grandpa";
else
return "invalid";
}
int main()
{
A a;
B b;
C c;
A p = NULL;
cout << verify(p) << endl;
p = &a;
cout << verify(p) << endl;
p = &b;
cout << verify(p) << endl;
p = &c;
cout << verify(p) << endl;
//system("pause");
}
对于一个类如果有虚函数,就会在这个类中创建一个虚表,也就会产生一个虚指针指向这个虚表。
既然有一个指针指向了虚表,这个类派生后,在派生类中就不必再创建虚表,如果派生类还有自己的虚函数,那么只在派生类中创建该虚函数的一个虚表,产生一个指向该虚表的指针。
为每个类设置虚表,初始化虚指针,为虚函数调用插入代码都是自动发生的,不必担心这些。
(我看到过虚继承下虚表问题的分析,直接继承下没看过,特此又分析了一下,修改)
#include<iostream>
using namespace std;
class A
{
public:
virtual void a(){};
};
class B:public virtual A
{
public:
virtual void b(){};
};
int main()
{
cout<<sizeof(A)<<endl;
cout<<sizeof(B)<<endl;
}
对于这个程序,你大概是在vc60下运行的吧,在vc下结果是4和12。我用的编译器是g++,对于这段程序的结果确实都为4
因编译器不同导致结果不同这个我倒是没注意,这样可以得出,对虚函数这里的处理机制和编译器也是有关的,g++编译器还是更符合新的标准。
把虚继承virtual去掉再运行,在codeblocks下,g++编译运行结果都为4 vc下编译运行结果也都为4
在分析一个例子:
#include<iostream>
using namespace std;
class A
{
char j[3];
public:
virtual void a(){};
};
class B:public A
{
char k[3];
public:
virtual void b(){};
};
class C:public B
{
char m[3];
public:
virtual void c(){};
};
int main()
{
cout<<sizeof(A)<<endl;
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
}
这个直接继承的例子,在vc下,codeblocks下结果都为 8 12 16
再看这个直接继承的例子:
#include<iostream>
using namespace std;
class A
{
public:
virtual void a(){};
};
class B:public A
{
public:
virtual void b(){};
};
class C:public B
{
public:
virtual void c(){};
};
int main()
{
cout<<sizeof(A)<<endl;
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
}
vc下河codeblocks下结果都为 4 这两个程序说明,直接继承下,输出结果应当是本类所占的字节加父类数据成员所占字节,父类的虚指针所占字节没有加上。
加入虚继承后:
#include<iostream>
using namespace std;
class A
{
char j[3];
public:
virtual void a(){};
};
class B:public virtual A
{
char k[3];
public:
virtual void b(){};
};
class C:public virtual B
{
char m[3];
public:
virtual void c(){};
};
int main()
{
cout<<sizeof(A)<<endl;
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
}
这段代码,在codeblocks下g++编译运行结果为:8 16 24
在vc60下编译运行结果为:8 20 32
能够分析出codeblocks下的结果是本类加上父类的结果。vc下是 本类加父类后又加了4个字节。
但是这段代码:
#include<iostream>
using namespace std;
class A
{
public:
virtual void a(){};
};
class B:public virtual A
{
public:
virtual void b(){};
};
class C:public virtual B
{
public:
virtual void c(){};
};
int main()
{
cout<<sizeof(A)<<endl;
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
}
codeblocks下编译运行结果为 4 4 4
vc下编译运行结果为:4 12 20
从结果来看,vc下是 本类加父类后又加了4个字节。而codeblocks结果就不再是本类加父类的结果(这个有点迷茫)。
我只能提供这么多信息了~
如果你有更好的解释可以给我留言,相互学习~
每个含有虚函数声明的类对象都有一个虚函数表,表里是所有的(从基类到派生类的)虚函数,对应有虚函数指针,它们根据指向的对象决定调用哪个函数。 如果注释掉 virtual 根本就不存在虚函数,也没有虚函数表及指针,所以基类指针只会调用基类的方法,而不会调用指针指向的派生类对象的方法。
以上就是关于C++基类子类中,虚函数究竟是怎样判断该调用哪个函数的全部的内容,包括:C++基类子类中,虚函数究竟是怎样判断该调用哪个函数的、c++不可以用指针直接调用基类的虚函数吗、C++关于虚函数,简单的基类指针的问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)