C++基类子类中,虚函数究竟是怎样判断该调用哪个函数的

C++基类子类中,虚函数究竟是怎样判断该调用哪个函数的,第1张

有虚函数时,每个对象的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++关于虚函数,简单的基类指针的问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/9576095.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-29
下一篇 2023-04-29

发表评论

登录后才能评论

评论列表(0条)

保存