请问?虚函数的存在必要是什么,设计者是出于怎样的考虑呢?
c++ 虚函数 虚函数表
#include <afx.h>
struct A{
virtual void Print(){printf("A,Print\n");}
void Print2(){printf("A,Print2\n");}
};
struct B:public A{
void Print(){printf("B,Print\n");}
void Print2(){printf("B,Print2\n");}
};
struct C:public B{
void Print(){printf("C,Print\n");}
void Print2(){printf("C,Print2\n");}
};
int main()
{
A a;
B b;
C c;
A *pA1 = &a;//指向a
A *pB1 = &b;//指向b
B *pB2 = &b;
A *pC1 = &c;//指向c
B *pC2 = &c;
C *pC3 = &c;
printf("模块1:\n");
pA1->Print();//A,Print
pA1->Print2();//A,Print2
printf("\n模块2:\n");
pB1->Print();//B,Print
pB2->Print();//B,Print
printf("非虚函数:\n");
pB1->Print2();//A,Print2
pB2->Print2();//B,Print2
printf("\n模块3:\n");//
pC1->Print();//C,Print
pC2->Print();//C,Print
pC3->Print();//C,Print
printf("非虚函数:\n");
pC1->Print2();//A,Print2
pC2->Print2();//B,Print2
pC3->Print2();//C,Print2
printf("\n模块4:\n");
a.Print();//A,Print
b.Print();//B,Print
c.Print();//C,Print
printf("非虚函数:\n");
a.Print2();//A,Print2
b.Print2();//B,Print2
c.Print2();//C,Print2
system("pause");
return 1;
}
/*
子类有多个虚函数,所以需要引入虚函数表来管理调用的是哪个类的虚函数
(ps:有说法,类似于字符串为'\0'结尾,虚函数表中,虚函数结尾标示的是表中后面还有几个虚函数)。
子类调用虚函数时,根据类的类型访问类的虚函数表,
强转为父类时访问的就是父类的虚函数表,
然后在虚函数表中索引该虚函数。
模块2,模块3 可以很明显的看到
1 定义父类的指针,指向子类的变量。
2 使用该虚函数
那么问题来了,不定义使用的此函数为虚函数时,根本不会引起这样的问题(费力不讨好,虚函数表还占内存)。
因为这样做,本身就是违反c++语义的行为。引入虚函数,虚函数表到底出于什么考虑呢?
结论:
而析构函数不定义为虚函数一般也不会出错,
只要不出现以上2个蛋碎无语的情况。
*/
一个接口 多种实现 运行时类型确定调用哪个实现
说实话,这个应该是初接触c++的人都懂的吧
一个接口 多种实现 运行时类型确定调用哪个实现
说实话,这个应该是初接触c++的人都懂的吧
我们就是觉得你其实没懂。
没懂,那怎么写出最顶上的这代码的?你理解了我写着代码的意图么?
不懂,道友具体点。
很有必要 把他的思想对应到现实生活中 你就更更明白
简单举个例子
你家养了猫和狗
你说一句话"滚回去"
如果实现的时候是虚函数方式 是猫听到了 就滚回猫窝
狗听到了就会狗窝
但如果不是虚函数方式
猫狗听见了都不会理你 谁知道你叫谁滚回去啊?
除非你说猫滚回去 或者 狗滚回去 那么他们才执行自己的动作 但是你不觉得麻烦吗?
其实调用的时候c.Print2();
前面的c已经是区分了猫和狗了。
一个接口 多种实现 运行时类型确定调用哪个实现
说实话,这个应该是初接触c++的人都懂的吧
不懂,道友具体点。
很有必要 把他的思想对应到现实生活中 你就更更明白
简单举个例子
你家养了猫和狗
你说一句话"滚回去"
如果实现的时候是虚函数方式 是猫听到了 就滚回猫窝
狗听到了就会狗窝
但如果不是虚函数方式
猫狗听见了都不会理你 谁知道你叫谁滚回去啊?
除非你说猫滚回去 或者 狗滚回去 那么他们才执行自己的动作 但是你不觉得麻烦吗?
其实调用的时候c.Print2();
前面的c已经是区分了猫和狗了。
所以我才会提出,没有虚函数功能照样运行,而虚拟函数表还要占内存。所以我很好奇什么时候才是真正该用虚函数的时候。
A * pSubA = NULL;
if( input() == 1 )
pSubA = new B;
else if( input() == 2 )
pSubA = new C;
pSubA->print();
return pSubA;
不懂,道友具体点。
很有必要 把他的思想对应到现实生活中 你就更更明白
简单举个例子
你家养了猫和狗
你说一句话"滚回去"
如果实现的时候是虚函数方式 是猫听到了 就滚回猫窝
狗听到了就会狗窝
但如果不是虚函数方式
猫狗听见了都不会理你 谁知道你叫谁滚回去啊?
除非你说猫滚回去 或者 狗滚回去 那么他们才执行自己的动作 但是你不觉得麻烦吗?
其实调用的时候c.Print2();
前面的c已经是区分了猫和狗了。
调用基类指针的时候!
什么时候需要用基类的指针来访问子类的虚函数?
什么时候需要用基类的指针来访问子类的虚函数?