如果一个函数被定义为虚函数,它究竟意味着什么?它与纯虚函数是相同的吗?
当前回答
来自维基百科的虚拟功能 ...
在面向对象编程中,在c++和Object Pascal等语言中,虚函数或虚方法是一种可继承和可覆盖的函数或方法,可以方便地进行动态分派。这个概念是面向对象编程(OOP)的(运行时)多态性部分的重要组成部分。简而言之,虚函数定义了要执行的目标函数,但在编译时可能不知道目标。
与非虚函数不同,当虚函数被重写时,派生最多的版本将用于类层次结构的所有级别,而不仅仅是创建它的级别。因此,如果基类的一个方法调用虚方法,将使用派生类中定义的版本,而不是基类中定义的版本。
这与非虚函数相反,非虚函数仍然可以在派生类中被重写,但“新”版本只会被派生类及其以下类使用,但根本不会改变基类的功能。
而. .
纯虚函数或纯虚方法是一种虚函数,如果派生类不是抽象的,则需要由派生类实现。
当纯虚方法存在时,类是“抽象的”,不能单独实例化。相反,必须使用实现纯虚方法的派生类。纯虚类根本没有在基类中定义,因此派生类必须定义它,否则派生类也是抽象的,不能实例化。只有没有抽象方法的类才能被实例化。
虚类提供了一种重写基类功能的方法,而纯虚类则需要这种方法。
其他回答
Virtual functions must have a definition in base class and also in derived class but not necessary, for example ToString() or toString() function is a Virtual so you can provide your own implementation by overriding it in user-defined class(es). Virtual functions are declared and defined in normal class. Pure virtual function must be declared ending with "= 0" and it can only be declared in abstract class. An abstract class having a pure virtual function(s) cannot have a definition(s) of that pure virtual functions, so it implies that implementation must be provided in class(es) that derived from that abstract class.
Simula、c++和c#在默认情况下使用静态方法绑定,程序员可以通过将特定方法标记为虚拟来指定它们应该使用动态绑定。 动态方法绑定是面向对象编程的核心。
面向对象编程需要三个基本概念:封装、继承和动态方法绑定。
的实现细节 抽象要隐藏在背后 简单的接口。 继承允许将新的抽象定义为 某些的扩展或改进 现有的抽象,获得一些 或者说它的所有特征 自动。 动态方法绑定允许新抽象显示其新抽象 行为,即使在上下文中使用 这需要旧的抽象。
来自维基百科的虚拟功能 ...
在面向对象编程中,在c++和Object Pascal等语言中,虚函数或虚方法是一种可继承和可覆盖的函数或方法,可以方便地进行动态分派。这个概念是面向对象编程(OOP)的(运行时)多态性部分的重要组成部分。简而言之,虚函数定义了要执行的目标函数,但在编译时可能不知道目标。
与非虚函数不同,当虚函数被重写时,派生最多的版本将用于类层次结构的所有级别,而不仅仅是创建它的级别。因此,如果基类的一个方法调用虚方法,将使用派生类中定义的版本,而不是基类中定义的版本。
这与非虚函数相反,非虚函数仍然可以在派生类中被重写,但“新”版本只会被派生类及其以下类使用,但根本不会改变基类的功能。
而. .
纯虚函数或纯虚方法是一种虚函数,如果派生类不是抽象的,则需要由派生类实现。
当纯虚方法存在时,类是“抽象的”,不能单独实例化。相反,必须使用实现纯虚方法的派生类。纯虚类根本没有在基类中定义,因此派生类必须定义它,否则派生类也是抽象的,不能实例化。只有没有抽象方法的类才能被实例化。
虚类提供了一种重写基类功能的方法,而纯虚类则需要这种方法。
虚函数或虚方法是一种函数或方法,其行为可以在继承类中被具有相同签名的函数覆盖
这并不是对虚函数的一个很好的解释。因为,即使成员不是虚成员,继承类也可以重写它。你可以自己去看看。
当函数以基类作为参数时,这种差异就会显现出来。当您将继承类作为输入时,该函数将使用被覆盖函数的基类实现。但是,如果该函数是虚函数,则使用派生类中实现的函数。
virtual关键字赋予c++支持多态的能力。当你有一个指向某个类的对象的指针时,例如:
class Animal
{
public:
virtual int GetNumberOfLegs() = 0;
};
class Duck : public Animal
{
public:
int GetNumberOfLegs() { return 2; }
};
class Horse : public Animal
{
public:
int GetNumberOfLegs() { return 4; }
};
void SomeFunction(Animal * pAnimal)
{
cout << pAnimal->GetNumberOfLegs();
}
在这个(愚蠢的)示例中,GetNumberOfLegs()函数根据所调用对象的类返回适当的数字。
现在,考虑函数“SomeFunction”。它不关心传递给它的是什么类型的animal对象,只要它是从animal派生的。编译器会自动地将任何Animal派生类强制转换为Animal,因为它是一个基类。
如果我们这样做:
Duck d;
SomeFunction(&d);
它会输出'2'。如果我们这样做:
Horse h;
SomeFunction(&h);
它会输出'4'。我们不能这样做:
Animal a;
SomeFunction(&a);
因为它不会编译,因为GetNumberOfLegs()虚函数是纯的,这意味着它必须通过派生类(子类)来实现。
纯虚函数主要用于定义:
A)抽象类
这些是基类,你必须从它们中派生出来,然后实现纯虚函数。
b)接口
这些是“空”类,其中所有的函数都是纯虚的,因此你必须派生然后实现所有的函数。