I just spotted this in some code:
class Foo {
[...]
private:
virtual void Bar() = 0;
[...]
}
Does this have any purpose?
(I am trying to port some code from VS to G++, and this caught my attention)
I just spotted this in some code:
class Foo {
[...]
private:
virtual void Bar() = 0;
[...]
}
Does this have any purpose?
(I am trying to port some code from VS to G++, and this caught my attention)
This is a pure virtual function that happens to be private. This makes it so that a derived class must implement the method. In this case Bar.
I think you may be confused b/c this is done to create "interfaces" in C++ and a lot of times people think of these as public. There are cases where you may want to define an interface that is private where a public method uses those private methods in order to ensure the order of how they are called. (I believe this is called the Template Method)
For a relatively bad example :)
class RecordFile { public: RecordFile(const std::string &filename); void process(const Record &rec) { // Call the derived class function to filter out // records the derived instance of this class does // not care about if (filterRecord(rec)) { writeRecordToFile(rec); } }; private: // Returns true if the record is of importance // and should be kept virtual bool filterRecord(const Record &rec) = 0; void writeRecordToFile(const Record &rec); };
ISO C++ 2003 explicitly allows it:
§10.3 states nothing about access specifier and contains even a footnote in the second clause stating in the context of virtual function overrides:
[...] Access control (clause 11) is not considered in determining overriding.
The code is fully legal.
Why is this useful?
Generally, you want to have a clear entry point into your class hierarchy by introducing a public non-virtual function which calls the virtual function then. This is called a Non Virtual Interface idiom or NVI. And the non-virtual function can be implemented as inline function.
class Foo {
public:
[...]
void bar() {
bar_impl();
}
private:
virtual void bar_impl() = 0;
[...]
}
class FooImpl1 : public Foo {
...
void bar_impl() override {
// ... do something here
}
}
class FooImpl2 : public Foo {
...
void bar_impl() override {
// ... do something here
}
}
std::unique_ptr<Foo> foo = std::make_unique<FooImpl2>{};
foo->bar();
So far so good... Now you realize you have a bunch of classes which implement Foo
and you need to debug bar_impl()
. You have a choice: putting a breakpoint in every single bar_impl()
because you don't know what object type has been created, or you can put the breakpoint into the non-virtual caller function bar
and step into the bar_impl()
from there. Furthermore, you can implement some logging in bar()
which is then called before and after all potential bar_impl()
calls or you can use a lock before bar_impl()
and introduce thread-safety for the entire hierarchy and so on...
Why using a private
virtual function instead of protected
?
Std IOStreams use NVI with protected
virtual functions. Merely it's about how you want your users to reuse the functionality. With protected
virtual function the derived type is able to call the virtual function of the base type. This might be a good or bad idea depending on the virtual function's side effects. For example, both base and derived virtual functions try to acquire a non-reentrant lock and end up in a deadlock. I generally, tend to write private
virtual functions to avoid such surprises and have clear responsibilities in the program. I know it can confuse new C++ developers, but that's not that hard to explain why this design is more advantageous. And actually, I was a novice in C++ as well and got it explained... Some more explanations on private virtual functions: https://isocpp.org/wiki/faq/strange-inheritance#private-virtuals
I'm going to quote a brief explanation from the great C++ FAQ Lite which sums it up well:
[23.4] When should someone use private virtuals?
Almost never.
Protected virtuals are okay, but private virtuals are usually a net loss. Reason: private virtuals confuse new C++ programmers, and confusion increases cost, delays schedule, and degrades risk.
New C++ programmers get confused by private virtuals because they think a private virtual cannot be overridden. After all, a derived class cannot access members that are private in its base class so how, they ask, could it override a private virtual from its base class? There are explanations for the above, but that's academic. The real issue is that almost everyone gets confused the first time they run into private virtuals, and confusion is bad.
Unless there is a compelling reason to the contrary, avoid private virtuals.
The C++ FAQ Lite was updated in the meantime:
By the way, it confuses most novice C++ programmers that private virtuals can be overridden, let alone are valid at all. We were all taught that private members in a base class are not accessible in classes derived from it, which is correct. However this inaccessibility by the derived class does not have anything to do with the virtual call mechanism, which is to the derived class. Since that might confuse novices, the C++ FAQ formerly recommended using protected virtuals rather than private virtuals. However the private virtual approach is now common enough that confusion of novices is less of a concern.
The usual "academic" answer is: access specifiers and virtuality are orthogonal - one does not affect the other.
A little more practical answer: private virtual functions are often used to implement the Template Method design pattern. In languages that do not support private virtual functions, the template method needs to be public although it is not really meant to be a part of the interface.
Parent
from main()
. –
Spouse It is a pure virtual function. Any final implementation that is dervied from "Foo" MUST implement the "Bar" function.
It makes the function pure virtual as opposed to virtual.
No implementation is provided by default and the intent is that the function implementation must be specified by an inheriting class. This can be overriden however.
You sometimes see complete classes where all member functions are specified as pure virtual in this manner.
These are Abstract Base Classes, sometimes referred to as Interface Classes, and the designer of the ABC is saying to you, "I have now idea how this functionality would be implemented for all specialisations of this base class. But, you must have all of these defined for your specialisation to work and you know how your object should behave".
Edit: Oops, just spotted the fact that the member pure virtual function is private. (Thanks Michael) This changes things slightly.
When this base class is inherited using private inheritance it changes things. Basically what the designer of the base class is doing is saying is that, when your derived class calls a non-private function in the base class. part of the behaviour has been delegated to your specialisation of the function in your derived class. The non-private member is doing "something" and part of that "something" is a call, via the pure virtual base class function, to your implementation.
So some public function in Foo is calling the Bar function inside Foo, and it is relying on the fact that you will provide a specialised implementation of the Bar function for your particular case.
Scott Meyers refers to this as "implemented in terms of".
BTW Just chuckling about the number of answers that were quickly deleted by people who also didn't see the "fine print" in the question! (-:
HTH
cheers,
The only purpose it seems to serve is to provide a common interface.
BTW even though a function is declared as private virtual, it can still be implemented and called with the class instance or from friends.
Nonetheless, this sort of things usually meant to serve as interface, yet I don't do it this way.
© 2022 - 2024 — McMap. All rights reserved.