The code scenario is as follows:
class ParentClass {
void foo();
virtual void doSomething() { foo(); }
};
class ChildClass : public ParentClass {
virtual void doSomething();
};
Now, is there a way to force the child class to call the parent class' doSomething()? Let's assume that calling foo() is vital and should always be called when doSomething() is called. The child class can of course call ParentClass::doSomething(), but it seems a bit "risky" as it is not enforced.
I have come up with a "dirty" solution which is something like this:
class ParentClass {
void foo();
void doSomething() final {foo(); doSomethingChild(); }
virtual void doSomethingChild() = 0;
};
class ChildClass : public ParentClass {
virtual void doSomethingChild();
};
This way, child classes have to do the implementation and foo() is always called, but the method is not the same anymore. Is there any solutions that are more elegant?
This is not a dirty solution, but the non-virtual interface idiom (or template method pattern) that you discovered by yourself.
By defining a non-virtual function that calls a virtual function (among other things), you force every implementation of your class to implement the behavior of the non-virtual. The implementation are only free to modify part of this behavior, that is, the call to the virtual function.
This is usually done like so:
class Base {
public:
void foo() {
//do stuff
fooImpl();
//do other stuff
}
private:
virtual void fooImpl(); //pure or not
};
class Derived : public Base {
private:
virtual void fooImpl(){
// Implement or change fooImpl behavior
}
};
Making the non virtual public and the virtual private ensures as well that nobody can call fooImpl on these classes, which is what you want as you need some stuff to be perfom before and/or after the call to fooImpl.
Let see could this work :
class parent {
void foo() {...}
virtual void doFinal() {...}
void doSomething (){foo(); doFinal();}
}
class child {
virtual void doFinal() {...}
}
So you can reimplement doFinal ans use doSmthing.
Related
I have an abstract base class with one purely virtual method:
class Base
{
public:
virtual void update() = 0;
};
Is there any way I could create a class that inherits from Base, overrides the update method, but still forces its children to implement an update method? Like this:
class Base2 : public Base
{
public:
void update() override
{
if(bSomeCondition)
{
update(); //Calls child's update method
}
}
virtual void update() = 0; // Obviously not like this
};
I know I could create two new purely virtual methods with slightly different names in Base2, and just override those in child classes, but I would really like to keep these method names if that would be possible.
I'm guessing this isn't possible?
You can provide a definition for a pure virtual function, just not inline.
class Base2 : public Base
{
public:
void update() override = 0;
};
void Base2::update() // Base2 is abstract regardless of this
{
if(bSomeCondition)
{
update();
}
}
However, this is not useful with the current implementation of Base2::update. Because a child class must override it anyway, Base2 version will not be called unless used explicitly:
class Child: public Base2
{
public:
void update() override
{
Base2::update(); //infinite recursion with such implementation
}
};
// the other way would be to require calling it explicitly at call site
std::unique_ptr<Base2> ptr = std::make_unique<Child>();
ptr->Base2::update();
What you should do is to provide an implementation and another pure virtual function (possibly protected) to be called:
class Base2 : public Base
{
public:
void update() override;
protected:
virtual void doStuff() = 0;
};
void Base2::update()
{
if(bSomeCondition)
{
doStuff(); //Calls child's update method
}
}
No, it is not possible and in my opinion it would be very illegible.
How do I make a base class virtual function so that it always is called when a derived class calls its version of the function? I know I can call the base classes function by writing something like BaseClass::foo() at the beginning of the the function DerivedClass::foo(), but what if I want it to be called by default, without the creator of the derived class even knowing that the base classes function does anything?
class BaseClass
{
BaseClass();
virtual void foo() {
printf("base");
}
}
class DerivedClass : public BaseClass
{
DerivedClass();
void foo() {
printf("derived");
}
}
int main()
{
DerivedClass dc;
dc.foo();
}
Should print:
base
derived
That's not directly possible. You could split the function in non-virtual foo on the base class and (pure) virtual fooCore on the derived classes:
class Base {
protected:
virtual void fooCore() = 0;
public:
void foo(){
// do stuff, then call method of derived class
this->fooCore();
}
};
class Derived {
protected:
void fooCore() override {
//actual
};
};
From the "outside" the call Base::foo() stays the same.
So assume there is class A with function foo.
Class A is the parent of a few classes which all have the function foo.
All of the child classes need the functionality of
A::foo and adds upon it.
For example:
class A
{
public:
void foo()
{
print('A');
}
};
class B:public A
{
public:
void foo()
{
print("B");
}
};
class C:public A
{
public:
void foo()
{
print("C");
}
};
void main()
{
B b;
C c;
c.foo()// now only goes to C::foo(), meaning print C. I want it to to also go into A::foo() meaning print AC
b.foo()//now only goes to B::foo(),meaning print B. want it to print AB
}
And if I want to add class D : A with foo function it will also do A::foo() and then D::foo()
Sorry if I am missing something obvious.
EDIT : since it wasn't clear the question was if there is an automatic way to do so.
EDIT : found a workaround:
class A
{
virtual void foo2(){}
public:
void foo()
{
print('A');
foo2();
}
};
class B:public A
{
void foo2()
{
print("B");
}
public:
};
class C:public A
{
void foo2()
{
print("C");
}
public:
};
void main()
{
B b;
C c;
c.foo()// now prints AC
b.foo()//now prints AB
}
seems redundant since now there are 2 functions now.
You can call the parent class's implementation of a function using A::foo().
In your case, simply adding that function call will achieve the result you want:
class B:public A
{
public:
void foo()
{
A::foo();
print("B");
}
};
As a side note, whenever you intend to override functions, you should declare it as virtual:
class A
{
public:
virtual void foo()
{
print('A');
}
};
And then when overriding it, use the override keyword:
class B:public A
{
public:
void foo() override
{
print("B");
}
};
What you've called a workaround is an established solution to this question, and whilst some people might call it a workaround many wouldn't.
Its even got a name that covers it. The non-virtual interface pattern.
herb sutter :- http://www.gotw.ca/publications/mill18.htm
One example from S.O., there's probably more:-
Non-virtual interface design pattern in C#/C++
I'd argue that this IS a way to do it automatically.
As to your aside that its redundant because there are 2 functions - well there were 2 before (the base version and derived version).
One benefit of this approach in some designs is that if the virtual method foo2 is pure virtual (which would make A abstract) then this forces all immediate derived classes to implement foo2. (I say immediate because if B derives from A it must implement foo2 but if C then derives from B C isn't forced to implement foo2, it has access to B::foo2 )
Lets say we have following hierarchy:
class Abstract
{
public:
virtual void foo() = 0;
};
class Base : public Abstract
{
public:
virtual void foo() override; //provides base implementation
};
class Derived : public Base
{
public:
virtual void foo() override; //provides derived implementation
};
If Base::foo() is ever called on the Derived object that object will desync and its data will be corrupted. It inherits Base's data structure and its manipulation but needs to perform additional operations so calling only the Base::foo() will omit these extra operations and as a result the Derived's state will be corrupted.
Therefore I would like to prevent direct call of Base implementation of foo so this:
Derived d;
d.Base::foo();
ideally, should give me a compile time error of some sorts. Or do nothing or otherwise be prevented.
However it might be I am violating the polymorphism rules and should use composition instead but that would require a lots of extra typing...
How about template method pattern:
class Abstract
{
public:
void foo() { foo_impl(); }
private:
virtual void foo_impl() = 0;
};
class Base : public Abstract
{
private:
virtual void foo_impl() override; //provides base implementation
};
class Derived : public Base
{
private:
virtual void foo_impl() override; //provides derived implementation
};
then
void test(Abstract& obj) {
obj.foo(); // the correct foo_impl() will be invoked
}
Derived d;
test(d); // impossible to call the foo_impl() of Base
You can explore the template method pattern. It allows for greater control of the execution of the methods involved.
class Abstract
{
public:
virtual void foo() = 0;
};
class Base : public Abstract
{
protected:
virtual void foo_impl() = 0;
public:
//provides base implementation and calls foo_impl()
virtual void foo() final override { /*...*/ foo_impl(); }
};
class Derived : public Base
{
protected:
virtual void foo_impl() override; //provides derived implementation
};
The pattern is seen in the iostreams library with sync() and pubsync() methods.
To prevent the direct calls and maintain the consistent state, you will need to get the final implementation of the foo method in the correct place in the stack. If the intent is to prohibit the direct call from the top of the hierarchy, then you can move the _impl methods up.
See also the non-virtual interface, the NVI pattern.
Bear in mind as well that the overriding methods do not have to have the same access specifier as the Abstract class. You could also just make the methods in the derived classes private or protected;
class Abstract
{
public:
virtual void foo() = 0;
};
class Base : public Abstract
{
virtual void foo() override; //provides base implementation
};
class Derived : public Base
{
virtual void foo() override; //provides derived implementation
};
Note: unless otherwise intended, changing the access specifier could be considered bad design - so basically if you do change the access specifier, there should should be a good reason to do so.
You can make all the foo() methods non-public, then have a non-virtual function in the Abstract class that simply calls foo.
Given the code below, why the compiler throws an error (saying that the method calc() is not member of Model2) when using Sub<Model2> instance, if the fn() is declared virtual, and works when the fn() is not virtual? What is going on?
class Model1
{
public:
void calc(){std::cout<<"Model1 calc"<<std::endl;}
};
class Model2
{
public:
void calc2(){std::cout<<"Model2 calc"<<std::endl;}
};
template<typename T>
class Super : public T
{
public:
virtual void fn() // comment virtual for resolution
{ T::calc(); }
};
template<typename T>
class Sub : public Super<T>
{
public:
void fn()
{ T::calc2(); }
};
int main()
{
Super<Model1> bes;
bes.fn();
Sub<Model2> sts1;
sts1.fn();
return 0;
}
virtual methods have to be instantiated in a template, whereas non-virtual methods don't.
Errors depending of T "requirement" happen at the moment of instantiation.
Non-virtual methods are instantiated only when used or explicit instantiated.
In your case, when not virtual, Super<Model2>::fn is never called (it is Sub<Model2>::fn).
In the virtual case, Super<Model2>::fn is not called, but has to be instanciated because it is virtual.