Use-cases of pure virtual functions with body?
Asked Answered
F

7

55

I recently came to know that in C++ pure virtual functions can optionally have a body.

What are the real-world use cases for such functions?

Fagaly answered 9/4, 2010 at 16:52 Comment(2)
seems like a dupe of #2089583Adigranth
@patros: None of the answers in that thread describe a real world use case. So, no, I don't think this is a dupe.Fagaly
C
49

The classic is a pure virtual destructor:

class abstract {
  public: 
    virtual ~abstract() = 0;
};

abstract::~abstract() {}

You make it pure because there's nothing else to make so, and you want the class to be abstract, but you have to provide an implementation nevertheless, because the derived classes' destructors call yours explicitly. Yeah, I know, a pretty silly textbook example, but as such it's a classic. It must have been in the first edition of The C++ Programming Language.

Anyway, I can't remember ever really needing the ability to implement a pure virtual function. To me it seems the only reason this feature is there is because it would have had to be explicitly disallowed and Stroustrup didn't see a reason for that.

If you ever feel you need this feature, you're probably on the wrong track with your design.

Caco answered 9/4, 2010 at 17:6 Comment(7)
One issue that a downvoter might have (for the record, I didn't downvote) is that there's really no strong reason to have a pure virtual destructor. If there's another pure virtual function, there's no reason for the dtor to be pure virtual (though it almost certainly should be virtual). If the dtor is the only pure virtual function, then there may really be no need for the class to be abstract.Buttock
@Michael: I know this critique. (In fact, I wrote pretty much that in my answer.) The problem is, I can't think of any good reason to implement a pure virtual function myself. As I wrote, if you feel you need to do that, it's pretty likely you're on the wrong track.Caco
@MichaelBurr that's ridiculous. it's forgetting about all other stuffs that are not methods. you can have a base abstract class that gives you some data field (because why duplicate when it's going to be shared by derivatives), and declare an interface or a concept at the same time.Disinterested
@Brian R. Bondy does offer a good reason: Having a function purely virtual forces derived classes to provide an implementation. This also makes the base class abstract. The function implementation in the base class can be useful for derived classes to call it in order to extend it.Publus
@Publus Actually, he doesn't provide a reason. After reading it I'm as out of ideas when I would need this as I was before.Caco
@Caco in the case where you want to force derived classes to provide their own implementation. This is what "= 0" means, they will have to implement the method. However, I would suggest putting the base implementation in a differently named function instead of using this pattern, as many coders are not aware of it and can overlook the base implementation.Publus
@brita: Please, I know what the syntax is for. (That's my answer your comment is under, after all.) I was saying that Brian's answer lacks a rational for when you would want to implement a pure virtual functions. And all you added to that was that you wouldn't do it. shrugCaco
A
48

Pure virtual functions with or without a body simply mean that the derived types must provide their own implementation.

Pure virtual function bodies in the base class are useful if your derived classes wants to call your base class implementation.

Anneliese answered 9/4, 2010 at 16:54 Comment(1)
I like this more than the accepted answer because it's simple and clear, which are the traits of truth. Thank you so much.Wuhu
B
17

One reason that an abstract base class (with a pure virtual function) might provide an implementation for a pure virtual function it declares is to let derived classes have an easy 'default' they can choose to use. There isn't a whole lot of advantage to this over a normal virtual function that can be optionally overridden - in fact, the only real difference is that you're forcing the derived class to be explicit about using the 'default' base class implementation:

class foo {
public:
    virtual int interface();
};

int foo::interface() 
{
    printf( "default foo::interface() called\n");
    return 0;
};


class pure_foo {
public:
    virtual int interface() = 0;
};

int pure_foo::interface()
{
    printf( "default pure_foo::interface() called\n");
    return 42;
}

//------------------------------------

class foobar : public foo {
    // no need to override to get default behavior
};

class foobar2 : public pure_foo {
public:
    // need to be explicit about the override, even to get default behavior
    virtual int interface();
};

int foobar2::interface()
{
    // foobar is lazy; it'll just use pure_foo's default
    return pure_foo::interface();
}

I'm not sure there's a whole lot of benefit - maybe in cases where a design started out with an abstract class, then over time found that a lot of the derived concrete classes were implementing the same behavior, so they decided to move that behavior into a base class implementation for the pure virtual function.

I suppose it might also be reasonable to put common behavior into the pure virtual function's base class implementation that the derived classes might be expected to modify/enhance/augment.

Buttock answered 9/4, 2010 at 17:30 Comment(2)
@RichardGeorge: can you explain what's not executing properly? It's working as I expect, but perhaps you're looking at a different use case than me.Buttock
@Micheal ,it works fine, i little bit messed up with my own use case , +1 for you.Karen
D
8

One use case is calling the pure virtual function from the constructor or the destructor of the class.

Dorris answered 9/4, 2010 at 16:54 Comment(8)
+1: This is in fact the main case. Some might say the only case.Polyp
But there's no such thing as a pure virtual constructor, which your post seems to imply.Polyp
@John: I read it different. However, I think calling virtual functions, pure or not, from ctors or detors is a pretty questionable practice anyway.Caco
Meh, it has very well defined behavior in the language, it never calls the override.Photobathic
@sbi: after reading your comment I re-read this post and found my reading comprehension circuits completely failed. I thought that @Dorris was saying what you actually said in your accepted reply. I would remove my u/v if I could.Polyp
@nobugz: Which is exactly why it is questionable. If you don't need the virtual function mechanism to kick in, why is the function virtual in the first place? I don't dispute that there are cases where doing this might be Ok (I wrote questionable, after all, not wrong), but I suppose they are pretty rare.Caco
@Caco - one reason may be that you don't want to write the same function as both non-virtual and virtual.Dorris
do you mean call the pure virtual function from the constructor of the derived or base class?Dareen
C
8

The almighty Herb Sutter, former chair of the C++ standard committee, did give 3 scenarios where you might consider providing implementations for pure virtual methods.

Gotta say that personally – I find none of them convincing, and generally consider this to be one of C++'s semantic warts. It seems C++ goes out of its way to build and tear apart abstract-parent vtables, then briefly exposes them only during child construction/destruction, and then the community experts unanimously recommend never to use them.

Cuprous answered 13/6, 2010 at 21:35 Comment(2)
That Sutter article is excellent. Cleared up some obscure ideas for me.Originate
I don't see the relation with abstract-parent vtables.Neddra
S
4

The only difference of virtual function with body and pure virtual function with body is that existence of second prevent instantiation. You can't mark class abstract in c++.

Seamount answered 9/4, 2010 at 16:54 Comment(0)
B
4

This question can really be confusing when learning OOD and C++. Personally, one thing constantly coming in my head was something like: If I needed a Pure Virtual function to also have an implementation, so why make it "Pure" in first place ? Why not just leaving it only "Virtual" and have derivatives, both benefit and override the base implementation ?

The confusion comes to the fact that many developers consider the no body/implementation as the primary goal/benefit of defining a pure virtual function. This is not true!

The absence of body is in most cases a logical consequence of having a pure virtual function. The main benefit of having a pure virtual function is defining a contract: By defining a pure virtual function, you want to force every derivative to always provide their own implementation of the function. This "contract aspect" is very important especially if you are developing something like a public API. Making the function only virtual is not so sufficient because derivatives are no longer forced to provide their own implementation, therefore you may loose the contract aspect (which can be limiting in the case of a public API).

As commonly said : "Virtual functions can be overrided, Pure Virtual functions must be overrided." And in most cases, contracts are abstract concepts so it doesn't make sense for the corresponding pure virtual functions to have any implementation.

But sometimes, and because life is weird, you may want to establish a strong contract among derivatives and also want them to somehow benefit from some default implementation while specifying their own behavior for the contract. Even if most book authors recommend to avoid getting yourself into these situations, the language needed to provide a safety net to prevent the worst! A simple virtual function wouldn't be enough since there might be risk of escaping the contract. So the solution C++ provided was to allow pure virtual functions to also be able to provide a default implementation.

The Sutter article cited above gives interesting use cases of having Pure Virtual functions with body.

Bertine answered 5/3, 2016 at 13:10 Comment(2)
Where is the Sutter article? I don't see it other than your remark in the final sentence "... the Sutter article cited above ...".Pleomorphism
@Pleomorphism Sorry, I've just forgot to include a link. The cited article was in @OfekShilon 's answer . The situation i described in my answer falls in case 2 of Sutter's articleBertine

© 2022 - 2024 — McMap. All rights reserved.