Calling Pure Virtual Function From Abstract Base Class Member Function?
Asked Answered
T

3

8

So, based on a cursory search, I already know that calling a virtual function (pure or otherwise) from a constructor is a no go. I have restructured my code to ensure that I am not doing that. While this causes the user of my classes to add an extra function call in their code, this is really not that big of a deal. Namely, instead of calling the constructor in a loop, they now call the function which (in fact!) increases performance of the code since we don't have the housekeeping of building and destroying the object in question every time.

However, I have stumbled across something interesting...

In the abstract class I have something like this:

// in AbstractClass.h:
class AbstractClass {
 public:
  AbstractClass() {}
  virtual int Func(); //user can override
 protected:
  // Func broken up, derived class must define these
  virtual int Step1() = 0;
  virtual int Step2() = 0;
  virtual int Step3() = 0;
// in AbstractClass.cpp:
int AbstractClass::Func() {
  Step1();
  // Error checking goes here
  Step2();
  // More error checking...
  // etc...
}

Basically, there is a common structure that the pure virtual functions follow most of the time, but if they don't Func() is virtual and allows the derived class to specify the order. However, each step must be implemented in derived classes.

I just wanted to be sure that there's nothing that I necessarily am doing wrong here since the Func() function calls the pure virtual ones. That is, using the base class, if you call StepX(), bad things will happen. However, the class is utilized by creating a derived object and then calling Func() (e.g. MyDerivedObject.Func();) on that derived object, which should have all the pure virtual functions overloaded properly.

Is there anything that I'm missing or doing incorrectly by following this method? Thanks for the help!

Thicken answered 2/7, 2013 at 1:32 Comment(4)
This is a textbook example of using the Non-Virtual Interface idiom to implement the Template Method pattern.Uteutensil
Just to clarify, there's a big difference between "calling virtual functions in a constructor" and "calling pure-virtual functions". The former is tricky and discouraged (though valid), the latter is flat-out wrong (and also not totally trivial to do).Parthenogenesis
Calling a virtual function in a constructor or destructor is not a "no go", unless you haven't bothered to understand how they work.Lunneta
@PeteBecker Here's the answer that I'm working from. #962632 and it's not that I haven't bothered to learn how they work, I'm new-ish to the OOP side of things.Ramburt
N
5

Func is calling the virtual ones, not the pure virtual ones. You would have to qualify the calls with a scope operator, i.e. AbstractClass::Step1() to call THAT (virtual pure) function. Since you are not, you will always get an implementation by a derived class.

Nystrom answered 2/7, 2013 at 1:41 Comment(3)
So no matter what I do, unless I do something REALLY hacky like AbstractClass::Step3(), the functions will be overridden by the derived class? Are there any red flags with this approach with regards to good C++ code practices?Ramburt
Actually, it's what makes OO and C++ powerful. You can write "procedures" where the derived class gets to specify the details. Think about a comm protocol. EstablishConnection(); while(!Done()) {SendRequest(); GetResponse();} TerminateConnection(); All of those methods could be "virtual", one derived class uses TCP, another uses even higher level "connection" mechanism, or a simpler point to point RS-232 protocol have nothing in their Establish/TerminateSession() methods. Yet you defined a small framework that can be implemented and extended easily.Nystrom
Thanks for the explanation. I'm fairly new to some of these OO concepts and I want to be as sharp as possible...Ramburt
S
1

A virtual function in a base class makes the derived classes able to override it. But it seems things stop there.

But if the base class virtual function is pure, that forces the derived classes to implement the function.

Salinas answered 11/12, 2013 at 0:43 Comment(0)
I
-1

As a side comment you can make the Step1, Step2, Step3 methods private so that you'll be prevented by the compiler from directly calling them.

Ibbie answered 9/6, 2014 at 7:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.