虚拟方法是否用于直到运行时才创建的方法? 我在理解C++中的虚拟方法的目的时遇到了一些困难。如果一个方法的对象不是在编译时创建的,那么它必须是虚拟的吗?例如,如果您必须在运行时选择一只农场动物,那么该动物的所有方法都需要是虚拟的,因为在用户选择一个之前,您不知道它是否将被创建。如果我错了,请纠正我。
阅读虚拟方法的用途。我还建议你们看看这本书。不,这是完全错误的。如果需要根据对象的类型选择方法,并且在编译时类型未知,则方法必须是虚拟的。如果您的代码如下所示:虚拟方法是否用于直到运行时才创建的方法? 我在理解C++中的虚拟方法的目的时遇到了一些困难。如果一个方法的对象不是在编译时创建的,那么它必须是虚拟的吗?例如,如果您必须在运行时选择一只农场动物,那么该动物的所有方法都需要是虚拟的,因为在用户选择一个之前,您不知道它是否将被创建。如果我错了,请纠正我。,c++,methods,runtime,virtual,C++,Methods,Runtime,Virtual,阅读虚拟方法的用途。我还建议你们看看这本书。不,这是完全错误的。如果需要根据对象的类型选择方法,并且在编译时类型未知,则方法必须是虚拟的。如果您的代码如下所示: Animal *x; if(y==2) { x = new Animal(); x->DoSomething(); } 编译器在运行时知道x的类型是“Animal”。所以它知道该调用哪个版本的“DoSomething”。但看看这个代码: Animal *x; if(y==1) x=new Zebra(); els
Animal *x;
if(y==2)
{
x = new Animal();
x->DoSomething();
}
编译器在运行时知道x
的类型是“Animal”。所以它知道该调用哪个版本的“DoSomething”。但看看这个代码:
Animal *x;
if(y==1) x=new Zebra();
else if (y==2) x=GetSomeAnimal();
else x=new Giraffe();
x->DoSomething();
Animal * a = new Pig();
这里,x
的类型在编译时是未知的。它可以是斑马、长颈鹿,也可以是GetSomeAnimal
函数返回的任何类型的动物。无法知道调用DoSomething
是否应该调用Zebra::DoSomething
,Giraffe::DoSomething
或其他完全不同的东西。所以Animal::DoSomething
需要是虚拟的
<> P>并显示它与所创建的内容无关,请考虑如下:
void MyFunction(Animal &x)
{
x.DoSomething();
}
void MyOtherFunction(int x)
{
Giraffe g;
Zebra z;
if(x==2) MyFunction(g);
else MyFunction(f);
}
这里很清楚,一只
长颈鹿和一只斑马将被创造出来。但是如果Animal::DoSomething
不是虚拟的,MyFunction
将同时调用Animal::DoSomething
而不是Giraffe::DoSomething
在长颈鹿和Zebra::DoSomething
在斑马上。(当然,如果你想这样,不要让方法虚拟化)嗯,<代码>虚拟是C++中支持多态性的东西(特别是一个)。
当您希望相同类型的不同对象(Animal
)根据上下文(无论Animal
实际上是Pig
还是Cow
或Chicken
还是…)表现不同时(getProduceName()
返回“pork”或“beef”或“egg”或…)您将该行为/功能设置为虚拟的
通常一个好的OOD会有很好的接口/实现分离。C++中使用继承与<>代码>抽象<代码>类/方法实现。
因此,实际上,当您使getProduceName()
polymorphic/virtual
时,您实际上是在试图从不同的实现(Pig
或Cow
或Chicken
或…)中提取接口(Animal
),以保护您的客户端代码不受不同实现的影响。这样,如果您必须支持一个新的实现,您就不必更改客户机代码,只要它符合接口Animal
所以要回答这个问题:如果一个方法的对象不是在编译时创建的,那么它是否必须是虚拟的
该方法是否为虚拟方法并不取决于对象的创建时间(编译/运行时)。这取决于您希望如何设计应用程序。使函数虚拟化
有助于从不同的实现中提取接口。如果某些函数(getOwnerName()
)在所有实现类({return ownerName;}
)中具有相同的实现,则不需要将其设为虚拟函数
PS:IMHO多态性是一个好的OOD的副产品,你不会设计你的类来实现“运行时多态性”,然后在你有一个好的OO设计时展示运行时多态性。虚拟函数的一个更重要的目的是允许旧代码调用新代码
想想这个。函数将汽车对象作为参数。假设它执行测试驾驶()、加油()、计算能力()、getStoppingDistance()等操作。所有这些方法都取决于您输入的车型
但是每年都有新车问世。现在,在现实世界中,我们只需导入一个XML文件,其中包含构成所有汽车的属性。但是为了论证,假设我们必须静态地这样做:每次我们发现新车,我们都必须重建我们的整个程序。如果我们的计划很大,这将非常不方便。在某种程度上,我们调用的是相同的函数,但在某种程度上我们不是,因为对象的类型不同。我们为什么要重新编译
虚拟功能来拯救!当汽车制造商发布新车时,他们会同时发布一个声明新类型的头文件(该类型继承自具有虚拟函数的公共基类)和一个库(定义特定方法的对象文件)。因此,我们不再重新编译应用程序,而是重新链接到这个新库。因此,旧代码(我们的应用程序)可以调用新代码(汽车附带的新库)。假设您有以下代码:
Animal *x;
if(y==1) x=new Zebra();
else if (y==2) x=GetSomeAnimal();
else x=new Giraffe();
x->DoSomething();
Animal * a = new Pig();
指针a
的静态类型为Animal
,动态类型为Pig
现在我们打电话来
a->MakeASound();
如果MakeASound
是虚拟的,则调用动态类型(Pig
)的MakeASound
方法
如果不是,则调用静态类型(Animal
)的MakeASound
,无论Pig
是否覆盖MakeASound
方法。为什么标记为“C”?C++没有“方法”;它们被称为“成员函数”。成员函数没有“其对象”。一本好书可能是一个很好的开始学习C++的方法。你不能在运行时创建方法(在C++中,也就是说),并且你不能在运行时创建对象(除了包含对象模板或类似的东西的“对象”的一些外来定义”之外。代码>如果需要,请执行