如果一个函数被定义为虚函数,它究竟意味着什么?它与纯虚函数是相同的吗?
当前回答
虚函数或虚方法是一种函数或方法,其行为可以在继承类中被具有相同签名的函数覆盖
这并不是对虚函数的一个很好的解释。因为,即使成员不是虚成员,继承类也可以重写它。你可以自己去看看。
当函数以基类作为参数时,这种差异就会显现出来。当您将继承类作为输入时,该函数将使用被覆盖函数的基类实现。但是,如果该函数是虚函数,则使用派生类中实现的函数。
其他回答
“Virtual”意味着该方法可以在子类中重写,但在基类中有一个可直接调用的实现。“纯虚拟”意味着它是一个没有直接可调用实现的虚拟方法。这样的方法必须在继承层次结构中至少重写一次——如果一个类有任何未实现的虚方法,该类的对象就不能被构造,编译就会失败。
@夸克指出,纯虚拟方法可以有一个实现,但由于纯虚拟方法必须被覆盖,所以不能直接调用默认的实现。下面是一个带默认值的纯虚方法的例子:
#include <cstdio>
class A {
public:
virtual void Hello() = 0;
};
void A::Hello() {
printf("A::Hello\n");
}
class B : public A {
public:
void Hello() {
printf("B::Hello\n");
A::Hello();
}
};
int main() {
/* Prints:
B::Hello
A::Hello
*/
B b;
b.Hello();
return 0;
}
根据注释,编译是否失败是特定于编译器的。至少在GCC 4.3.3中,它不会编译:
class A {
public:
virtual void Hello() = 0;
};
int main()
{
A a;
return 0;
}
输出:
$ g++ -c virt.cpp
virt.cpp: In function ‘int main()’:
virt.cpp:8: error: cannot declare variable ‘a’ to be of abstract type ‘A’
virt.cpp:1: note: because the following virtual functions are pure within ‘A’:
virt.cpp:3: note: virtual void A::Hello()
纯虚函数
试试这段代码
#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函数在基类中被标记为虚函数。它表示编译器尝试在派生类中搜索函数并实现该函数。如果没有找到,则执行基本的一个。谢谢
虚方法可以被派生类覆盖,但需要基类中的实现(将要被覆盖的基类)。
纯虚方法没有基类的实现。它们需要由派生类定义。(所以从技术上讲,覆盖不是正确的术语,因为没有什么可以覆盖)。
当派生类重写基类的方法时,Virtual对应于默认的java行为。
纯虚方法对应于抽象类中的抽象方法的行为。而只包含纯虚方法和常量的类则是接口的cppp -pendant。
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....因为语言是他们写的。
虚函数或虚方法是一种函数或方法,其行为可以在继承类中被具有相同签名的函数覆盖
这并不是对虚函数的一个很好的解释。因为,即使成员不是虚成员,继承类也可以重写它。你可以自己去看看。
当函数以基类作为参数时,这种差异就会显现出来。当您将继承类作为输入时,该函数将使用被覆盖函数的基类实现。但是,如果该函数是虚函数,则使用派生类中实现的函数。