pure virtual vs virtual functions

Pages: 12
This still seems strange.

Why put the common code in the pure virtual function then? Why not make it a protected member function with a different name? That seems much less error prone and funky.
I possibly didn't explain it properly...

Implementing a body for a pure virtual function can be used as a mechanism for providing a 'safer than usual' default implementation for a simple virtual function.

I know with a simple explanation it is always possible to say, 'but in that case you can do X' but the idea goes like this.

You are designing a base class for a number child classes. You have a function that you can see is common to all the classes that you are designing but may be different in future classes. So you put the common code in the base class and make it virtual so future development can implement different code if need be. Now if it is critical that this default code is checked to make sure it is appropriate for the child class you can make the function pure virtual. Now in any future development the developer has to pay a bit more attention to this function, hence it is safer and less error prone.
Most simply said ...

*pure virtual methods have no body - if they had an implementetion they would not be realy virtual functions. They exists only for future implementation in inheriting classes.

*the difference between a pure virtual method and a declaration in notation is a "= 0" assignment in the method name.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdlib.h>
#include <iostream>

using namespace std;


class IHuman{

public:
    virtual void sayHi() = 0;
};

class Britisher : public IHuman{
public:
    void sayHi(){
        cout << "Hello\n";
    }
};

class Polak : public IHuman{
public:
    void sayHi(){
        cout << "Siemanko\n";
    }
};

int main(int argc, char** argv) {

    IHuman *human = new Britisher;
    human->sayHi();
    delete human;

    human = new Polak;
    human->sayHi();
    delete human;

    string pressEnter;
    getline(cin, pressEnter);

    return (EXIT_SUCCESS);
}


*a class that has at least 1 pure virtual method becomes an abstract class. As said you can not create object from absract classes. it is strictly characteristic for polymorphism - using one name for many methods in different types of objects highly interrelated between self.

*as we see the same line "human->sayHi();" does two completly different things. It means that for every type the correct method will be executed - data are processed in the right - specific for them - way.

*defined overrides of the pure virtual methods must be identical (with the same number and type of parameters) in each class

I just love them :)
Last edited on
@ Grey Wolf:

I think I get what you're saying, but it seems to me like that's a poor design approach in pretty much any situation I can think of.

If the pure virtual function contains only "common support" code and doesn't actually perform the expected task in full, then it clearly should be named differently. It's kind of misleading if my JumpRope() function doesn't actually JumpRope, but instead gets the rope ready to be jumped. It'd make much more sense to have a seperate PrepareRopeForJumping() function.

If it can be used in full by some child classes, but not for all child classes, that's kind of the perfect situation to use a non-pure virtual function. The child class can reimplement it at its descrition.
You are designing a base class for a number child classes. You have a function that you can see is common to all the classes that you are designing but may be different in future classes. So you put the common code in the base class and make it virtual so future development can implement different code if need be. Now if it is critical that this default code is checked to make sure it is appropriate for the child class you can make the function pure virtual. Now in any future development the developer has to pay a bit more attention to this function, hence it is safer and less error prone.


So in the end, it boils down to name convention and lazyness again. Your argument is simply, that it's better to implement the default behaviour in the pure virtual, because then the function feels "the same" and coders don't be tricked into thinking, that other (non-virtual protected) functions are actually a default implementation, right?

1
2
3
4
5
6
7
8
9
struct base
{
    virtual void foo() = 0;
};
struct der : base
{
    virtual void foo() { base::.... // here the programmer ask himself what the default implementation may be.
    // your argument is, he chooses "base::foo" just because it yields the same name hence it seems "natural" to call to this.
};


as for the lazyness, it's just easier to not have to declare the second function in base, so go for that?

Well, I have to say that I find these arguments not convincing. I brought up a couple of arguments like

1) the presence of the pure virtual default implementation is not in the interface and hence unexpected. Most developer just are not expecting an implementation of pure virtuals (even knowing that its possible). You have to rely on comments to tell the developer, that it IS in fact possible to call the base class function
2) You can't change the modifier. It will always bear the same as in the base class (most of the time: public).
3) You can only provide one default implementation.

(Note, that 2) and 3) apply for all virtual functions, not only pure virtuals.)

There is only one really showstopper for the case of "use pure virtual implementations" for me, and that's the template thingie. I tried to make a compiling example, but I can't figure out the syntax of how to call a member function of a specific class over a member function pointer. Maybe its not even possible in C++.. (Edit: It's not possible.)

1
2
3
4
5
6
7
8
9
10
11
12
13
template <class B, void(B::*fn)()> 
struct Caller
{
    void call(B& obj)
    { 
        if ( check_whether_allowed_to_call_derrived_classes(obj) )
            (obj.*fn)();
        else
        {
            // call obj.B::*fn - version. Couldn't find the syntax. Maybe its not even possible.
        }
    }
};


But hey, guys... I mean.. really... REALLY.. even if someone gets the syntax right here - that's not an argument 99% of the time, is it?


So my resume is still the same: Use non-virtual protected methods with similar name, except you would plan to make it public anyway (but then you should think of your class design) and you care about too many functions in your class namespace (then you should really think about your class design. Maybe it's too crowded anyway).

Ciao, Imi.

PS: For more information about this topic, I recommend Scott Meyer, "Effective C++", Item Chapter 36. He doesn't come up with the template-thingie nor with my point 1) above. But he mentioned all the other arguments we had so far, including the description Grey Wolf brought up ;-).
Last edited on
I am not advocating the use of this, I was just addressing the question; Doesn't providing a function body defeat the entire point of having a pure virtual function?
FYI: I wrote to Scott Meyer and ask him about whether my case with the template call is possible in C++. He replied that it's not.

You can't hold a pointer to a virtual function in a base class directly. The call over the function pointer will always yield in a "normal" virtual function call.

I tried and he's right! :-D (at least my compiler agrees)

1
2
3
4
5
6
7
8
9
10
struct B { virtual void foo() { cout << "B" << endl; } };
struct D:B {
	virtual void foo() { cout << "D" << endl; }
	void bar() {
		typedef void(B::*FN)();
		FN fn = &B::foo;
		(this->*fn)(); // prints out "D", not "B".
	}
};
int main () { D().bar(); }


Ciao, Imi.
Last edited on
Topic archived. No new replies allowed.
Pages: 12