Let's say I have a fist class
class Walker {
public:
Walker();
virtual ~Walker();
virtual void Step();
};
Then a second one, deriving from the former
class Mecha : public Walker {
public:
Mecha();
virtual ~Mecha();
private:
virtual void Step();
};
Is that private modifier on Step() any useful? Mecha::Step() can still be called as Walker::Step(), isn't it? Shouldn't there be a warning as I'm trying to change the nature of the super-class through the definition of its sub-class?
Can a sub-class affect visibility of virtual methods?
Yes, they can change the visibility of the methods.
Is that private modifier on Step() useful?
Depends. It primarily affects the client of the code.
Increasing the visibility (e.g. going from protected to public) may be useful, but comes with a warning on it's use - the implementer of the base class interface desired that method to be internal to the hierarchy, making it external could break things... (possible implementations of the template method pattern come to mind).
Principally, changing the visibility doesn't affect the polymorphic nature of the virtual method - it still is overridden in the derived class. It does however affect the caller. Changing the method to private limits client code to calling the method from a pointer or reference to the base class and not the derived.
Mecha m;
//m.Step(); // fails to compile
Walker& w = m;
w.Step(); // still calls Mecha::Step()
Further, changing the method to protected would allow further sub-classes to call it.
No, making Step() private does not change the polymorphic behaviour. There's no warning since the language explicitly allows this. (But note that Java doesn't).
But it does prevent your being able to write Mecha::Step() explicitly unless you code that in a member function of Mecha.
Related
Why does this happen?
http://coliru.stacked-crooked.com/a/e1376beff0c157a1
class Base{
private:
virtual void do_run() = 0;
public:
void run(){
do_run();
}
};
class A : public Base {
public:
// uplift ??
virtual void do_run() override {}
};
int main()
{
A a;
a.do_run();
}
Why can I override a PRIVATE virtual method as public?
According to https://en.cppreference.com/w/cpp/language/virtual#In_detail overriding a base's virtual member function only care about the function name, parameters, const/volatile-ness and ref qualifier. It doesn't care about return type, access modifier or other things you might expect it to care about.
The linked reference also specifically notes that :
Base::vf does not need to be visible (can be declared private, or inherited using private inheritance) to be overridden.
Nothing that I can find explicitly gives permission to do this, but the rules of overriding do not prevent it. It's allowed by virtue of virtual functions and function overriding existing and not disallowing this case.
If you are asking why this is how the language is, you may have to ask the standardization committee.
That behavior is intended. If a method is virtual then it's meant to be customizable by derived classes, regardless of access modifier.
See here
Why I can override PRIVATE virtual method as public???
Because you look at the base method being private at wrong angle. B::do_run being private means "only members and friends of this class can use it". To prohibit derived classes from overriding it we would need separate specifier but we can simply make it not virtual. Class A on another side allows anybody to call A::do_run() and it is up to class A designer to decide so. So there is no uplift as you see it.
Notice that this implementation does not change the way how the base class is accessed and a construct:
Base& b = a;
b.do_run();
will not work.
I remember there is some rationale behind it described in more detail in "Effective C++" by Scott Meyers. But the key practical feature is to be able to use such flexibility in the opposite direction, to override public base class members with private functions in a derived class forcing the client to use the base class as the interface and not be tempted to use directly the derived one that should remain a hidden implementation.
If the intention is to write a private code for the base-class & to prevent the possibility of override it, implement the private function in the base class, and declare it final, otherwise: When should someone use private virtuals? ISOCPP.ORG FAQ
Sometimes I accidentally forget to call the superclass's method in C++ when I override a method.
Is there any way to help figure out when I'm overriding a method with, so that I don't forget to call the superclass's method? (Something like Java's #Override, except that C++ doesn't have annotations...)
One suggestion is the Non-Virtual Inferface Idiom. I.e., make your public methods non-virtual and have them call private or protected virtual methods that derived classes can override to implement their specific behavior.
If you don't have control over the base class, you could perhaps use an intermediate class:
class Foo // Don't control this one
{
public:
virtual void action();
};
class Bar : public Foo // Intermediate base class
{
public:
virtual void action()
{
doAction();
Foo::action();
}
protected:
virtual void doAction() = 0;
};
Derive your classes from Bar and override doAction() on each. You could even have doBeforeAction() and doAfterAction() if necessary.
With regards to Java's #Override, there is a direct equivalent in C++11, namely the override special identifier.
Sadly, neither #Override nor override solve the problem since: (a) they're optional; (b) the responsibility of calling the base class's method still rests with the programmer.
Furthermore, I don't know of any widely available method that would address the problem (it's quite tricky, esp. given that you don't necessarily want to call the base class's method -- how is the machine to know?).
Unfortunately Í'm not aware of a common mechanism to do this.
In C++ if you're needing to use the base class's functionality in addition to added child functionality you should look at the template method pattern. This way the common logic always lives in the base class and there's no way to forget to execute it, and you override in the child only the piece you need to change.
I'm extending a class provided by a third part library. The class, let's call it Foo, has a reset() method which can be called in order to restart Foo's behavior. The reset() method is also used internally by the class.
class Foo
{
public:
void reset () {
/* ... */
}
void something () {
reset();
}
};
So far, I need to overload the reset() method in order to reset my additional features as well:
class Bar : public Foo
{
public:
void reset() {
/* ...something... */
Foo::reset();
}
};
Unfortunately, since the Foo::reset() method is not virtual, by calling Bar::something() I get the Foo::reset() method called instead of Bar::reset().
Is there a way (different from overloading Foo::something() as well) to make it backward-virtual?
You cannot extend classes that were not intended to be extended.
You can't make reset() virtual in your library in such a way that it will affect the base class without changing the base class's code. For starters, the compiler has not added the necessary bookkeeping code that allows it to make virtual calls to reset().
There is no 'clean way' of doing it using inheritance. Virtual is a compile/link time difference: using a vtable to resolve method at runtime (virtual) vs direct linking (non-virtual).
No this is not possible. The virtualness of a method is decided when the method is declared and you cannot change it later in a base class.
To allow you to do so would be nothing short of a disaster. Virtual methods simply behave differently than non-virtual methods and it must be accounted for when designing an object. With this proposal I would have to consider that all of my methods could behave in 2 distinctly different ways. That significantly adds to the design cost of the application and reduces the reliability.
If neither reset nor something are virtual, you're screwed, and that's the end of the story. If something is virtual you could override it. However, if these necessary methods aren't virtual, then the class isn't intended to be extended (or implemented properly, if it was intended).
Edit:
You COULD try composition, e.g.
class Bar {
Foo f;
// foo's methods, etc, wrapped here
void something() {
f.reset();
reset();
}
};
But if you need the whole, implicit conversion, thing, you're still stuffed.
Why would I want to define a C++ interface that contains private methods?
Even in the case where the methods in the public scope will technically suppose to act like template methods that use the private methods upon the interface implementation, even so, we're telling the technical specs. right from the interface.
Isn't this a deviation from the original usage of an interface, ie a public contract between the outside and the interior?
You could also define a friend class, which will make use of some private methods from our class, and so force implementation through the interface. This could be an argument.
What other arguments are for defining a private methods within an interface in C++?
The common OO view is that an interface establishes a single contract that defines how objects that conform to that interface are used and how they behave. The NVI idiom or pattern, I never know when one becomes the other, proposes a change in that mentality by dividing the interface into two separate contracts:
how the interface is to be used
what deriving classes must offer
This is in some sense particular to C++ (in fact to any language with multiple inheritance), where the interface can in fact contain code that adapts from the outer interface --how users see me-- and the inner interface --how I am implemented.
This can be useful in different cases, first when the behavior is common but can be parametrized in only specific ways, with a common algorithm skeleton. Then the algorithm can be implemented in the base class and the extension points in derived elements. In languages without multiple inheritance this has to be implemented by splitting into a class that implements the algorithm based in some parameters that comply with a different 'private' interface. I am using here 'private' in the sense that only your class will use that interface.
The second common usage is that by using the NVI idiom, it is simple to instrument the code by only modifying at the base level:
class Base {
public:
void foo() {
foo_impl();
}
private:
virtual void foo_impl() = 0;
};
The extra cost of having to write the dispatcher foo() { foo_impl(); } is rather small and it allows you to later add a locking mechanism if you convert the code into a multithreaded application, add logging to each call, or a timer to verify how much different implementations take in each function... Since the actual method that is implemented in derived classes is private at this level, you are guaranteed that all polymorphic calls can be instrumented at a single point: the base (this does not block extending classes from making foo_impl public thought)
void Base::foo() {
scoped_log log( "calling foo" ); // we can add traces
lock l(mutex); // thread safety
foo_impl();
}
If the virtual methods were public, then you could not intercept all calls to the methods and would have to add that logging and thread safety to all the derived classes that implement the interface.
You can declare a private virtual method whose purpose is to be derivated. Example :
class CharacterDrawer {
public:
virtual ~CharacterDrawer() = 0;
// draws the character after calling getPosition(), getAnimation(), etc.
void draw(GraphicsContext&);
// other methods
void setLightPosition(const Vector&);
enum Animation {
...
};
private:
virtual Vector getPosition() = 0;
virtual Quaternion getRotation() = 0;
virtual Animation getAnimation() = 0;
virtual float getAnimationPercent() = 0;
};
This object can provide drawing utility for a character, but has to be derivated by an object which provides movement, animation handling, etc.
The advantage of doing like this instead of provinding "setPosition", "setAnimation", etc. is that you don't have to "push" the value at each frame, instead you "pull" it.
I think this can be considered as an interface since these methods have nothing to do with actual implementation of all the drawing-related stuff.
Why would I want to define a C++
interface that contains private
methods?
The question is a bit ambiguous/contradictory: if you define (purely) an interface, that means you define the public access of anything that connects to it. In that sense, you do not define an interface that contains private methods.
I think your question comes from confusing an abstract base class with an interface (please correct me if I'm wrong).
An abstract base class can be a partial (or even complete) functionality implementation, that has at least an abstract member. In this case, it makes as much sense to have private members as it makes for any other class.
In practice it is rarely needed to have pure virtual base classes with no implementation at all (i.e. base classes that only define a list of pure virtual functions and nothing else). One case where that is required is COM/DCOM/XPCOM programming (and there are others). In most cases though it makes sense to add some private implementation to your abstract base class.
In a template method implementation, it can be used to add a specialization constraint: you can't call the virtual method of the base class from the derived class (otherwise, the method would be declared as protected in the base class):
class Base
{
private:
virtual void V() { /*some logic here, not accessible directly from Derived*/}
};
class Derived: public Base
{
private:
virtual void V()
{
Base::V(); // Not allowed: Base::V is not visible from Derived
}
};
When I declare a base class, should I declare all the functions in it as virtual, or should I have a set of virtual functions and a set of non-virtual functions which I am sure are not going to be inherited?
A function only needs to be virtual iff a derived class will implement that function in a different way.
For example:
class Base {
public:
void setI (int i) // No need for it to be virtual
{
m_i = i;
}
virtual ~Base () {} // Almost always a good idea
virtual bool isDerived1 () // Is overridden - so make it virtual
{
return false;
}
private:
int m_i;
};
class Derived1 : public Base {
public:
virtual ~Derived () {}
virtual bool isDerived1 () // Is overridden - so make it virtual
{
return true;
}
};
As a result, I would error the side of not having anything virtual unless you know in advance that you intend to override it or until you discover that you require the behaviour. The only exception to this is the destructor, for which its almost always the case that you want it to be virtual in a base class.
You should only make functions you intend and design to be overridden virtual. Making a method virtual is not free in terms of both maintenance and performance (maintenance being the much bigger issue IMHO).
Once a method is virtual it becomes harder to reason about any code which uses this method. Because instead of considering what one method call would do, you must consider what N method calls would do in that scenario. N represents the number of sub classes which override that method.
The one exception to this rule is destructors. They should be virtual in any class which is intended to be derived from. It's the only way to guarantee that the proper destructor is called during deallocation.
The non-virtual interface idiom (C++ Coding Standards item 39) says that a base class should have non-virtual interface methods, allowing the base class to guarantee invariants, and non-public virtual methods for customization of the base class behaviour by derived classes. The non-virtual interface methods call the virtual methods to provide the overridable behaviour.
I tend to make only the things I want to be overridable virtual. If my initial assumptions about what I will want to override turn out to be wrong, I go back and change the base class.
Oh, and obviously always make your destructor virtual if you're working on something that will be inherited from.
If you are creating a base class ( you are sure that somebody derives the class ) then you can do following things:
Make destructor virtual (a must for base class)
Define methods which should be
derived and make them virtual.
Define methods which need not be ( or
should not be) derived as
non-virtual.
If the functions are only for derived
class and not for base class then mark
them as protected.
Compiler wouldn't know which actual piece of code will be run when pointer of base type calls a virtual function. so the actual piece of code that would be run needs to be evaluated at run-time according to which object is pointed by base class pointer. So avoid the use of virtual function if the function is not gonne be overriden in an inherited class.
TLDR version:
"you should have a set of virtual functions and a set of non-virtual functions which you are sure are not going to be inherited." Because virtual functions causes a performance decrease at run-time.
The interface functions should be, in general, virtual. Functions that provide fixed functionality should not.
Why declare something virtual until you are really overriding it? I believe it's not a question of being sure or not. Follow the facts: is it overriden somewhere? No? Then it must not be virtual.