ChatGPT解决这个技术问题 Extra ChatGPT

Virtual/pure virtual explained

What exactly does it mean if a function is defined as virtual and is that the same as pure virtual?


z
zeel

From Wikipedia's Virtual function ...

In object-oriented programming, in languages such as C++, and Object Pascal, a virtual function or virtual method is an inheritable and overridable function or method for which dynamic dispatch is facilitated. This concept is an important part of the (runtime) polymorphism portion of object-oriented programming (OOP). In short, a virtual function defines a target function to be executed, but the target might not be known at compile time.

Unlike a non-virtual function, when a virtual function is overridden the most-derived version is used at all levels of the class hierarchy, rather than just the level at which it was created. Therefore if one method of the base class calls a virtual method, the version defined in the derived class will be used instead of the version defined in the base class.

This is in contrast to non-virtual functions, which can still be overridden in a derived class, but the "new" version will only be used by the derived class and below, but will not change the functionality of the base class at all.

whereas..

A pure virtual function or pure virtual method is a virtual function that is required to be implemented by a derived class if the derived class is not abstract.

When a pure virtual method exists, the class is "abstract" and can not be instantiated on its own. Instead, a derived class that implements the pure-virtual method(s) must be used. A pure-virtual isn't defined in the base-class at all, so a derived class must define it, or that derived class is also abstract, and can not be instantiated. Only a class that has no abstract methods can be instantiated.

A virtual provides a way to override the functionality of the base class, and a pure-virtual requires it.


So... is pure virtual a keyword, or just a term that is used?
virtual void Function() = 0; is a pure virtual. The "= 0" indicates is purity.
Justin, 'pure virtual' is just a term (not a keyword, see my answer below) used to mean "this function cannot be implemented by the base class. As Goz said, adding the "=0" to the end of a virtual function makes it "pure"
I believe Stroustrup said that he wanted to add a pure keyword, but that Bell Labs was about to make a major release of C++, and his manager wouldn't allow it at that late stage. Adding keywords is a big deal.
This is not a good answer. Any method can be overriden, not just virtual ones. See my answer for more details.
T
Tom Church

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.

Consider the following code:

#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();
}

What is the output of this program?

Base NonVirtual called.
Base Virtual called.
Base NonVirtual called.
Derived Virtual called.

Derived overrides every method of Base: not just the virtual one, but also the non-virtual.

We see that when you have a Base-pointer-to-Derived (bDerived), calling NonVirtual calls the Base class implementation. This is resolved at compile-time: the compiler sees that bDerived is a Base*, that NonVirtual is not virtual, so it does the resolution on class Base.

However, calling Virtual calls the Derived class implementation. Because of the keyword virtual, the selection of the method happens at run-time, not compile-time. What happens here at compile-time is that the compiler sees that this is a Base*, and that it's calling a virtual method, so it insert a call to the vtable instead of class Base. This vtable is instantiated at run-time, hence the run-time resolution to the most-derived override.

I hope this wasn't too confusing. In short, any method can be overridden, but only virtual methods give you polymorphism, that is, run-time selection of the most derived override. In practice, however, overriding a non-virtual method is considered bad practice and rarely used, so many people (including whoever wrote that Wikipedia article) think that only virtual methods can be overridden.


Just because the Wikipedia article (which I am no way defending) defines a virtual method "as one that can be overridden in subclasses" doesn't exclude the possibility that other, non-virtual, methods with the same name can be declared. This is known as overloading.
The definition is nonetheless incorrect. A method that can be overridden in a derived class is not virtual by definition; whether the method can be overridden is irrelevant to the definition of "virtual". Also, "overloading" usually refers to having multiple methods with the same name and return type but different arguments, in the same class; it is very different from "overriding" which implies exactly the same signature but in a derived class. When it is done non-polymorphically (non-virtual base), it is often called "hiding".
This should be the accepted answer. That particular Wikipedia article Which I will take the time to link here since nobody else on this question has done it, is complete garbage. +1, good sir.
NOW it makes sense. Thank you, good sir, for properly explaining that any method can be overriden by derived classes and the change is in how the compiler will behave to choose what function is called in different situations.
It might be helpful to add a Derived* with the same function calls to drive the point home. Otherwise great answer
J
JBRWilkinson

The virtual keyword gives C++ its' ability to support polymorphism. When you have a pointer to an object of some class such as:

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();
}

In this (silly) example, the GetNumberOfLegs() function returns the appropriate number based on the class of the object that it is called for.

Now, consider the function 'SomeFunction'. It doesn't care what type of animal object is passed to it, as long as it is derived from Animal. The compiler will automagically cast any Animal-derived class to a Animal as it is a base class.

If we do this:

Duck d;
SomeFunction(&d);

it'd output '2'. If we do this:

Horse h;
SomeFunction(&h);

it'd output '4'. We can't do this:

Animal a;
SomeFunction(&a);

because it won't compile due to the GetNumberOfLegs() virtual function being pure, which means it must be implemented by deriving classes (subclasses).

Pure Virtual Functions are mostly used to define:

a) abstract classes

These are base classes where you have to derive from them and then implement the pure virtual functions.

b) interfaces

These are 'empty' classes where all functions are pure virtual and hence you have to derive and then implement all of the functions.


In your example, you can't do #4 because you didn't provide an implementation of the pure virtual method. It's not strictly because the method is pure virtual.
@iheanyi You can't provide implementation to pure virtual method in base class. Hence case #4 is still error.
a
aniskhan001

In a C++ class, virtual is the keyword which designates that, a method can be overridden (i.e. implemented by) a subclass. For example:

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;
};

In this case a subclass can override the the initShape function to do some specialized work:

class Square : public Shape
{
  public: 
    Square();
    virtual ~Square();

  protected:
    virtual void initShape() // override the Shape::initShape function
    {
      setName("Square");
    }
}

The term pure virtual refers to virtual functions that need to be implemented by a subclass and have not been implemented by the base class. You designate a method as pure virtual by using the virtual keyword and adding a =0 at the end of the method declaration.

So, if you wanted to make Shape::initShape pure virtual you would do the following:

class Shape 
{
 ...
    virtual void initShape() = 0; // pure virtual method
 ... 
};

By adding a pure virtual method to your class you make the class an abstract base class which is very handy for separating interfaces from implementation.


Regarding "virtual functions that must be implemented by a subclass" -- that's not strictly true, but the subclass is also abstract if they are not. And abstract classes cannot be instantiated. Also, "cannot be implemented by the base class" seems misleading; I'd suggest that "have not been" would be better since there is no restriction to modifications of the code to add an implementation within the base class.
And "the getName function cannot be implemented by a subclass" isn't quite right. Subclasses can implement the method (w/the same or different signature) but that implementation will not OVERRIDE the method. You could implement Circle as a subclass and implement "std::string Circle::getName()" -- then you could call either method for a Circle instance. But if used through a Shape pointer or reference the compiler would call Shape::getName().
Good points on both fronts. I was trying to stay away from discussing special cases for this example, I'll modify the answer to be more forgiving. Thanks!
@NickHaddad Old thread, but wondering why you called your variable m_name. What does the m_ mean?
@Tqn assuming NickHaddad has followed conventions, m_name is a naming convention commonly called the Hungarian notation. The m indicates member of a structure/class, integer.
J
John Millikin

"Virtual" means that the method may be overridden in subclasses, but has an directly-callable implementation in the base class. "Pure virtual" means it is a virtual method with no directly-callable implementation. Such a method must be overridden at least once in the inheritance hierarchy -- if a class has any unimplemented virtual methods, objects of that class cannot be constructed and compilation will fail.

@quark points out that pure-virtual methods can have an implementation, but as pure-virtual methods must be overridden, the default implementation can't be directly called. Here is an example of a pure-virtual method with a default:

#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;
}

According to comments, whether or not compilation will fail is compiler-specific. In GCC 4.3.3 at least, it won't compile:

class A {
public:
    virtual void Hello() = 0;
};

int main()
{
    A a;
    return 0;
}

Output:

$ 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()

it must be overridden if you want to instantiate an instance of the class. If you don't create any instances then the code will compile just fine.
compilation will not fail. If there is no implementation of a (pure) virtual method then that class/object cannot be instantiated. It may not LINK, but it will compile.
@Glen, @tim: on which compiler? When I try to compile a program which builds an abstract class, it doesn't compile.
@John Compilation will only fail if you try to instantiate an instance of a class that contains a PVF. You can of course instantiate pointer or reference values for such classes.
Also, John, the following isn't quite right: "'Pure virtual' means it is a virtual method with no implementation." Pure virtual methods can have implementations. But you can't call them directly: you have to override and use the base class implementation from within the sub-class. This allows you to provide a default part of the implementation. It's not a common technique though.
P
Pang

A virtual function is a member function that is declared in a base class and that is redefined by derived class. Virtual function are hierarchical in order of inheritance. When a derived class does not override a virtual function, the function defined within its base class is used.

A pure virtual function is one that contains no definition relative to the base class. It has no implementation in the base class. Any derived class must override this function.


A pure virtual function can have its implementation in the base class.
M
McMurdo

How does the virtual keyword work?

Assume that Man is a base class, Indian is derived from man.

Class Man
{
 public: 
   virtual void do_work()
   {}
}

Class Indian : public Man
{
 public: 
   void do_work()
   {}
}

Declaring do_work() as virtual simply means: which do_work() to call will be determined ONLY at run-time.

Suppose I do,

Man *man;
man = new Indian();
man->do_work(); // Indian's do work is only called.

If virtual is not used, the same is statically determined or statically bound by the compiler, depending on what object is calling. So if an object of Man calls do_work(), Man's do_work() is called EVEN THOUGH IT POINTS TO AN INDIAN OBJECT

I believe that the top voted answer is misleading - Any method whether or not virtual can have an overridden implementation in the derived class. With specific reference to C++ the correct difference is run-time (when virtual is used) binding and compile-time (when virtual is not used but a method is overridden and a base pointer is pointed at a derived object) binding of associated functions.

There seems to be another misleading comment that says,

"Justin, 'pure virtual' is just a term (not a keyword, see my answer below) used to mean "this function cannot be implemented by the base class."

THIS IS WRONG! Purely virtual functions can also have a body AND CAN BE IMPLEMENTED! The truth is that an abstract class' pure virtual function can be called statically! Two very good authors are Bjarne Stroustrup and Stan Lippman.... because they wrote the language.


Unfortunately once an answer starts getting upvoted, all the others will be ignored. Even tho they could be better.
P
PJT

Simula, C++, and C#, which use static method binding by default, the programmer can specify that particular methods should use dynamic binding by labeling them as virtual. Dynamic method binding is central to object-oriented programming.

Object oriented programming requires three fundamental concepts: encapsulation, inheritance, and dynamic method binding.

Encapsulation allows the implementation details of an abstraction to be hidden behind a simple interface. Inheritance allows a new abstraction to be defined as an extension or refinement of some existing abstraction, obtaining some or all of its characteristics automatically. Dynamic method binding allows the new abstraction to display its new behavior even when used in a context that expects the old abstraction.


j
johannes_lalala

Virtual methods CAN be overridden by deriving classes, but need an implementation in the base class (the one that will be overridden)

Pure virtual methods have no implementation the base class. They need to be defined by derived classes. (So technically overridden is not the right term, because there's nothing to override).

Virtual corresponds to the default java behaviour, when the derived class overrides a method of the base class.

Pure Virtual methods correspond to the behaviour of abstract methods within abstract classes. And a class that only contains pure virtual methods and constants would be the cpp-pendant to an Interface.


T
Tunvir Rahman Tusher

Pure Virtual Function

try this code

#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();
}

In class anotherClass remove the function sayHellow and run the code. you will get error!Because when a class contain a pure virtual function, no object can be created from that class and it is inherited then its derived class must implement that function.

Virtual function

try another code

#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!

}

Here the sayHellow function is marked as virtual in base class.It say the compiler that try searching the function in derived class and implement the function.If not found then execute the base one.Thanks


Haha, it took me a long 30 seconds to understand what is wrong here... HelloW :)
c
can

"A virtual function or virtual method is a function or method whose behavior can be overridden within an inheriting class by a function with the same signature" - wikipedia

This is not a good explanation for virtual functions. Because, even if a member is not virtual, inheriting classes can override it. You can try and see it yourself.

The difference shows itself when a function take a base class as a parameter. When you give an inheriting class as the input, that function uses the base class implementation of the overriden function. However, if that function is virtual, it uses the one that is implemented in the deriving class.


S
Sohail xIN3N

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.


Same note as to @rashedcs: Indeed a pure virtual function can have its definition...