如果一个函数被定义为虚函数,它究竟意味着什么?它与纯虚函数是相同的吗?
当前回答
虚函数是在基类中声明并由派生类重新定义的成员函数。虚函数是按继承顺序分层的。 当派生类不重写虚函数时,将使用在其基类中定义的函数。
纯虚函数是指相对于基类不包含任何定义的虚函数。 它在基类中没有实现。任何派生类都必须重写此函数。
其他回答
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)接口
这些是“空”类,其中所有的函数都是纯虚的,因此你必须派生然后实现所有的函数。
I'd like to comment on Wikipedia's definition of virtual, as repeated by several here. [At the time this answer was written,] Wikipedia defined a virtual method as one that can be overridden in subclasses. [Fortunately, Wikipedia has been edited since, and it now explains this correctly.] That is incorrect: any method, not just virtual ones, can be overridden in subclasses. What virtual does is to give you polymorphism, that is, the ability to select at run-time the most-derived override of a method.
考虑下面的代码:
#include <iostream>
using namespace std;
class Base {
public:
void NonVirtual() {
cout << "Base NonVirtual called.\n";
}
virtual void Virtual() {
cout << "Base Virtual called.\n";
}
};
class Derived : public Base {
public:
void NonVirtual() {
cout << "Derived NonVirtual called.\n";
}
void Virtual() {
cout << "Derived Virtual called.\n";
}
};
int main() {
Base* bBase = new Base();
Base* bDerived = new Derived();
bBase->NonVirtual();
bBase->Virtual();
bDerived->NonVirtual();
bDerived->Virtual();
}
这个程序的输出是什么?
Base NonVirtual called.
Base Virtual called.
Base NonVirtual called.
Derived Virtual called.
Derived重写Base的每个方法:不仅是虚方法,而且是非虚方法。
我们看到,当你有一个基类指向派生类的指针(bDerived)时,调用NonVirtual调用基类实现。这是在编译时解析的:编译器看到bDerived是一个Base*,而NonVirtual不是virtual,所以它在类Base上进行解析。
然而,调用Virtual调用派生类实现。由于关键字virtual,方法的选择发生在运行时,而不是编译时。这里在编译时发生的事情是,编译器看到这是一个Base*,并且它正在调用一个虚方法,所以它插入一个对虚表的调用,而不是类Base。此虚表在运行时实例化,因此运行时解析为最派生的覆盖。
我希望这不会让你太困惑。简而言之,任何方法都可以被覆盖,但只有虚方法可以提供多态性,即运行时选择派生最多的覆盖。然而,在实践中,覆盖非虚拟方法被认为是不好的实践,很少被使用,所以很多人(包括撰写维基百科文章的人)认为只有虚拟方法可以被覆盖。
virtual关键字是如何工作的?
假设人是一个基类,那么印度人就是由人演变而来的。
Class Man
{
public:
virtual void do_work()
{}
}
Class Indian : public Man
{
public:
void do_work()
{}
}
将do_work()声明为virtual仅仅意味着:调用哪个do_work()只在运行时决定。
假设我这样做了,
Man *man;
man = new Indian();
man->do_work(); // Indian's do work is only called.
如果不使用virtual,则由编译器静态确定或静态绑定相同的对象,具体取决于调用的对象。因此,如果Man的对象调用do_work(),则Man的do_work()将被调用,即使它指向一个印度对象
我相信投票最多的答案是误导性的——任何方法,无论是否虚,都可以在派生类中有一个重写的实现。具体到c++,正确的区别是相关函数的运行时(使用virtual时)绑定和编译时(不使用virtual但重写方法且基指针指向派生对象时)绑定。
似乎还有另一个误导性的评论说,
“贾斯汀,‘纯虚拟’只是一个术语(不是关键字,请看我的回答 下面)用来表示“此函数不能由基实现。 类。”
这是错误的! 纯虚函数也可以有一个体并且可以实现!事实上,抽象类的纯虚函数可以被静态调用!两位非常优秀的作者是Bjarne Stroustrup和Stan Lippman....因为语言是他们写的。
在c++类中,virtual是一个关键字,它表示一个方法可以被子类重写(即由子类实现)。例如:
class Shape
{
public:
Shape();
virtual ~Shape();
std::string getName() // not overridable
{
return m_name;
}
void setName( const std::string& name ) // not overridable
{
m_name = name;
}
protected:
virtual void initShape() // overridable
{
setName("Generic Shape");
}
private:
std::string m_name;
};
在这种情况下,子类可以覆盖initShape函数来做一些专门的工作:
class Square : public Shape
{
public:
Square();
virtual ~Square();
protected:
virtual void initShape() // override the Shape::initShape function
{
setName("Square");
}
}
术语纯虚指的是需要由子类实现而基类还没有实现的虚函数。通过使用virtual关键字并在方法声明的末尾添加a =0,可以将一个方法指定为纯虚拟方法。
所以,如果你想让Shape::initShape纯虚拟,你会做以下事情:
class Shape
{
...
virtual void initShape() = 0; // pure virtual method
...
};
通过向类中添加纯虚方法,可以使类成为抽象基类 这对于将接口与实现分离非常方便。
纯虚函数
试试这段代码
#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{
public:
virtual void sayHellow()=0;
};
class anotherClass:aClassWithPureVirtualFunction
{
public:
void sayHellow()
{
cout<<"hellow World";
}
};
int main()
{
//aClassWithPureVirtualFunction virtualObject;
/*
This not possible to create object of a class that contain pure virtual function
*/
anotherClass object;
object.sayHellow();
}
在类anotherClass中,删除sayhello函数并运行代码。你会得到错误!因为当一个类包含一个纯虚函数时,不能从该类创建对象,并且它是继承的,那么它的派生类必须实现该函数。
虚函数
试试其他代码
#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{
public:
virtual void sayHellow()
{
cout<<"from base\n";
}
};
class anotherClass:public aClassWithPureVirtualFunction
{
public:
void sayHellow()
{
cout<<"from derived \n";
}
};
int main()
{
aClassWithPureVirtualFunction *baseObject=new aClassWithPureVirtualFunction;
baseObject->sayHellow();///call base one
baseObject=new anotherClass;
baseObject->sayHellow();////call the derived one!
}
这里sayhello函数在基类中被标记为虚函数。它表示编译器尝试在派生类中搜索函数并实现该函数。如果没有找到,则执行基本的一个。谢谢