pure virtual vs virtual functions

Pages: 12
Can anyone tell me the difference ( if any ) between pure virtual functions and virtual functions?
If you have a pure virtual, the class becomes abstract. You cannot create an object of it.
pure virtual functions have no body (the function must be implemented in child classes)

virtual functions have a body (the function may be reimplemented in child classes, but it isn't required).

Any class that has 1 or more pure virtual functions are "abstract". Abstract objects cannot be instantiated -- you can only instantiate its child classes.

EDIT: doh, too slow
Last edited on
closed account (1yR4jE8b)
A virtual function could possibly have an implementation in the class where it is defined, whereas a pure virtual function does not.

virtual:
1
2
3
4
5
6
7
class Foo
{
     virtual void bar()
     {
          do stuff;
     }
}


pure virtual:
1
2
3
4
class Foo
{
     virtual void bar() = 0;
}
Do you have to put const = 0 after the function declaration?

E.g.,
1
2
3
4
class  Foo
{
     virtual void bar() const = 0;
}


Besides, is it true that you CANNOT do anything that would lead to the change of any piece of data inside a pure virtual function?
'const' means the function is const. Don't put it there if the function isn't const.

' = 0' means the function is pure virtual. Don't put it there if the function isn't pure virtual.

is it true that you CANNOT do anything that would lead to the change of any piece of data inside a pure virtual function?


No. That's a const function. (and yes, that is true of const functions, with the exception of mutable members, but that's another topic)

virtual functions don't have to be const, though. Remember they're two different things.
Last edited on
Besides, is it true that you CANNOT do anything that would lead to the change of any piece of data inside a pure virtual function?


And beside.. there is no such thing as "inside a pure virtual function". That's the whole idea: you have no real function, only the declaration.

Another hint: Never try to call pure virtual functions from your own class constructor. It won't work correctly. (It doesn't work with "normal" virtual functions as expected either, but for pure virtuals, its fatal.)

Ciao, Imi.
I seem to recall that pure virtual functions may have a definition in the class in which they are declared but the class remains abstract and the implementation can only be executed explicitly. Consider the re-use gained in the following example:

1
2
3
4
5
6
/* Abstract.hpp */

struct Abstract
{
    virtual void f() = 0;
};

1
2
3
4
5
/* Abstract.cpp */

void Abstract::f() {
    // common implementation details
}


1
2
3
4
5
6
/* Class.hpp */

struct Class : public Abstract
{
    virtual void f();
};

1
2
3
4
5
6
7
/* Class.cpp */

void Class::f() {
    // perform common implementation
    Abstract::f();
    // add class-specific implementation details
}


Last edited on
Pure virtual is a declaration. A class that declares a pure virtual function can provide an implementation. And there are legitimate cases where this can be used.
I seem to recall that pure virtual functions may have a definition in the class in which they are declared but the class remains abstract and the implementation can only be executed explicitly.


Oh, yea.. that one.. forgot about this. Yes, you can provide the implementation. It's mostly used for pure-virtual destructors, which in turn are mostly used if you want to make *something* pure virtual to make the class abstract, but can't think of which function you should.


Your example is usable for "reusing functions" as well, but I'd stll prefer to implement f as a "normal" protected helper function (non-virtual), as this is what I consider "more normal". And since it's private, it would not be able to call it from outside (which is usually not wanted). And finally, you can provide different default implementation variants (just with different names).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct Abstract
{
    virtual void f() = 0;
protected:
    void doCommonStuff();
    void doSomeMoreCommonStuff();
};
...
struct Class : Abstract
{
    void f()
    {
        // perform common implementation
        doCommonStuff();
        if (needToDoMoreStuff()) doSomeMoreCommonStuff(); // still common implementation
        ...
    }
}


But at the end of the day, it's a lot of personal taste here.. Your way is feasible too..

Ciao, Imi.
Last edited on
Your example is usable for "reusing functions" as well, but I'd stll prefer to implement f as a "normal" protected helper function (non-virtual), as this is what I consider "more normal". And since it's private, it would not be able to call it from outside (which is usually not wanted). And finally, you can provide different default implementation variants (just with different names).


I agree, protected helper method(s) are a better idea. It's not really my way but rather something I've come across in the past. I remember thinking, "I didn't know we could that."
The example moorecm posted is a well recognised pattern (in some circles). And its meaning and context are clear. Calling a helper doesn't quite convey the same meaning.

It forces the user of the class to provide an implementation (even though that implementation may be the default one).
The example moorecm posted is a well recognised pattern (in some circles).


In which circles?

Sorry if this might sount bluntly, but actually I really don't know. I very very very seldom see implementations of pure virtual functions in the wild and if its almost always the destructor. But I haven't come around too much in C++ code for the past years, so maybe I missed out some very interesting pattern? ;-)


And its meaning and context are clear. Calling a helper doesn't quite convey the same meaning.

It forces the user of the class to provide an implementation (even though that implementation may be the default one).


Can you elaborate where my version does things different? Or is the only point that the "helper function" in my example is named completely different and hence may not be associated as beeing "a default implementation of f()"?

Well, if so, I could have named it "default_f()". :-D The reasoning I provide still stands: you cannot make pure virtual default implementation protected, nor you can provide multiple versions. Both you can (or can choose not to) with the independend function.

Even another disadvantage arise with using pure virtual implementations: They are not part of the interface. Since your default implementation surely should be communicated to all users of the class (they are the one who should call it), it should be stated somewhere, hence you have to rely to comments.

1
2
3
struct Abstract {
    virtual void f() = 0; // there IS an implementation you can use, if you like
};


This looks more cumbersome to me than just expressing it in code.


To get a bit more into the topic, the only real reason I see to use the default implementation of a pure virtual function instead of an protected, non-virtual replacement is: templates.

When you access the default implementation in a generic way (without ugly macros), you are bound to the symbol of the original name. You can not just generic add some "default_" before the name. (If you are with the back to the wall and a gun between your eyes, there may be some ugly techniques involving member function templates, but I better spare this one. ;)

Other than that, I don't see any advantages, only disadvantages of using the implementation of a pure virtual as default implementation.

Ciao, Imi.
Last edited on
In which circles?

Sorry if this might sount bluntly, but actually I really don't know.

If I thought this was common practice, I wouldn't have mentioned it. But as I said, it is a used pattern and moorcm posted it as an example and I explained it.


Can you elaborate where my version does things different?

No.


This looks more cumbersome to me than just expressing it in code.

Like I said, it's a pattern and conveys specific meaning to those who understand it.
If I thought this was common practice, I wouldn't have mentioned it. But as I said, it is a used pattern and moorcm posted it as an example and I explained it.


Lol.


Kbw.. No, it's not a common pattern. And it's not even "a little recognized".


Like I said, it's a pattern and conveys specific meaning to those who understand it.


...and it conveys no specific meaning. It's just an inferior way (most of the time) of providing a default implementation to subclasses.


Ciao, Imi.
Do whatever makes you happy.
Doesn't providing a function body defeat the entire point of having a pure virtual function?

Why not just have a non-pure virtual function?
Yeah, IMO it doesn't make much sense to implement the function if you're going to force the derived classes to also implement it. Sure, you can do it, but is it sensible?
closed account (z05DSL3A)
Doesn't providing a function body defeat the entire point of having a pure virtual function?

No, having a pure virtual function body mean that a child must implement their own version of the function but common code can still be called from the base class.
Last edited on
Pages: 12