Allow descendant to call overridden protected function on instance of another descendant - c++

Suppose we have a base class Base with a public interface, and some protected methods that are used to support the public interface. Simplified example:
class Base {
protected:
virtual int helper() const = 0;
public:
virtual void do_work() {
//By default, just call the helper. Descendants can customize behaviour.
int x = helper();
do_something_with_an_int(x);
}
};
And suppose we have some descendants DerivedA, DerivedB, DerivedC ... that implement this interface.
The reason I want to split up the work in two functions (rather than just use do_work to do everything) is because I want to have a special descendant that might look something like this:
class DescendantWrapper : Base {
Base *impl;
int x;
protected:
int helper() const override {
x += impl->helper();
}
public:
void do_work() override {
helper();
if(some_internal_condition()) {
do_some_other_thing_with_an_int(x);
} else {
x = 0;
}
}
};
The intention is to allow DescendantWrapper to wrap any descendant of Base, and take the place of that descendant in some other code. Of course, the other code would not be aware that its descendant of Base has been wrapped.
The problem is that a derived class (in this example, DescendantWrapper) cannot call a protected method on an instance of its parent class (in this example, Base::helper()).
One solution is to specifically declare DescendantWrapper as a friend of Base. However, this means that other users of this code couldn't create their own descendant wrappers. Does anyone know an alternative to friend functions in this scenario?

Related

Private overriden virtual functions in derived class

Is there any point to making virtual member functions, overridden from a base class private, if those are public in the base class?
struct base {
virtual void a();
};
struct derived : base {
// ...
private:
void a() override;
};
If you are forced to do a 2-phase construction on the implementation class (i.e. have an init() method as well as or instead of a constructor that has to be called (I know, but there are reasons), then this stops you calling any /other/ methods directly on the instance pointer before you pass it back as an interface pointer. Go the extra mile, make the inheritance private, and have your one public init function return the interface pointer!
Another reason is you just don't /need/ to write public: in a final implementation class declaration, so then by default everything is private. But why you would do that and use struct instead of class I don't know. Perhaps this was converted from class at some point due to a style war?
Looking at your design, I see one cannot call derived::a directly, but only through a base interface.
Is there any point? Consider that, once we have a derived instance, we can always up-cast to its base, so given
derived d;
while d.a() wouldn't compile, we can always do
base & b = d;
b.a(); //which actually calls derived::a
In other words: derived::a is not that private, after all, and I would discourage this design, which can be confusing to the user.
Things change if the members private in derived are private in base, as well: this time it is clear that they just cannot be called directly, outside base or derived.
Let's say we have a couple of functions, and want them to be called conditionally, according to a value passed as an argument to a third one:
struct base
{
void dosomething(bool x)
{
if(x)
{
do_this();
}
else
{
do_that();
}
}
private:
virtual void do_this(){}
virtual void do_that(){}
};
Thus a derived class could be like:
struct derived : base
{
private:
void do_this() override { }
void do_that() override { }
};
and no other class can call them, unless it extended base itself:
derived d;
d.dosomething(true); //will call do_this() in derived
d.dosomething(false); //will call do_that() in derived
d.do_that() //won't compile
Yes, if you inherit the base class as private. Otherwise, it is more of a weird explicit-like restriction - user has to has to make an explicit conversion to use the function - it is generally ill advised as few will be able to comprehend the author's intention.
If you want to restrict some functions from base class, make a private/protected inheritance and via using keyword declare which base-methods you want to be protected/public in the derived class.
The same reasoning as for non-virtual methods applies: If only the class itself is supposed to call it make it private.
Consider the template method pattern:
struct base {
void foo() { a() ; b(); }
virtual void a() = 0;
virtual void b() = 0;
};
struct derived : base {
private:
void a() override {}
void b() override {}
};
int main()
{
derived().foo();
}
Perhaps a and b should have been protected, but anyhow the derived can change accesibility and it requires some documentation so that derived knows how it is supposed to implement a and b.

How can I implement internal abstract member classes in c++?

An abstract class has internal virtual functions.
Can an abstract class have internal virtual classes to be implemented later?
I tried the following:
#include <bits/stdc++.h>
using namespace std;
class C1 {
public:
class Child {
int tmp;
virtual int getint() = 0;
};
virtual Child getChild() = 0;
};
class C2: public C1 {
public:
class Child {
int getint()
{
return 10;
}
} c;
Child getChild()
{
return c;
}
};
int main() { return 0; }
Child is an abstract class which will be overrode in derived classes. And I hope the implemented Child can be used to define a function.
However, I got an error:
invalid abstract return type for member function 'virtual C1::Child C1::getChild()'
Can't I implement an internal abstract class in derived classes, just like implementing a virtual function?
In the present code, class C1::Child and class C2::Child have no inheritance relationship. Hence they are totally unrelated classes. Even if you relate them with inheritance, then also getChild() cannot return Child (value). It can return either Child& (reference) or Child* (pointer) to form a valid virtual methods with covariance. Refer: C++ virtual function return type
Such errors are easily caught by using override specifier available in C++11.
Without knowing the exact context of what you are trying to achieve, the possible code should look like this:
class C1 {
// ... same
virtual Child& getChild() = 0;
// ^^^^^^ reference
};
class C2 : public C1 {
// ^^^^^^ did you miss this?
public:
class Child : public C1::Child {
// ^^^^^^^^^ inheritance
int getint() override { return 10; }
} c;
Child& getChild() override { return c; }
};
Also your below statement seems confusing:
"Child is a abstract class, which will be implemented later,"
Like virtual methods, the classes don't have such runtime relationships.
The best meaning of "implementing later" in the context of class is -- implementing it outside the body of the enclosing class, such as:
class Outer { public: class Inner; };
// ...
class Outer::Inner { ... };
Theoretically, Abstract Classes are used for creating Interfaces. Using Interfaces, clients demand the required functionality. By defining/implementing Interfaces, servers fulfill the client's functionality. Interface/Abstract Class are simply blueprint of requirement/agreement between client and server. The classes which implement the Interface/Abstract Class or fulfills the functionality requirement can be instantiated. So there can be many implementation of the same Interface/Abstract Class. Now in order to access all these different implementation of the same Interface/Abstract Class seamlessly at different point of time, we need a generalized way. And this generalized way is via pointer(*) or reference(&) to the underlying Interface\Abstract Class.
In your code C1::Child is an anAbstract Class or Interface.
So, C1::getChild() can return an implementation of the Interface/Abstract C1::Child. But it cannot return an instance of the Interface/Abstract C1::Child itself as per above theoretical explanation. And hence the error.
Proper way to declare C1::getChild() would be:
virtual C1::Child* getChild() = 0; or
virtual C1::Child& getChild() = 0;
Also, C1::Child can be simply seen as a class inside namespace C1, since class is also a kind of namespace with some restriction.
From your post you seem to be confusing things. I suggest you get a re-read on abstract classes and try some simple examples yourself.
Child is a abstract class, which will be implemented later, And I hope
the implemented Child can be used to define a function.
A pure virtual method (virtual int getint() = 0; in your example) is not meant to be implemented "later". It's meant to be implemented by an override method in a derived class.
E.g. if you have
class Child {
virtual int getint() = 0;
};
you cannot do
class Child {
virtual int getint() { return 10; }
};
nor
int Child::getint() { return 10; }
at a later time.
What you can do is:
class Derived : public Child
{
int getint() override { return 10; }
};

How to make an inherited virtual function not usable?

I have an abstract base class which declares a pure virtual function (virtual method() = 0;). Some of the inherited classes specialize and use this method but there's one of those inherited classes in which I don't want to make this method usable. How do I do it? Is making it private the only choice?
Well, you could throw that will make tacking where it is called easier.
void method() override { throw /* whatever */ ; }
Dynamic polymorphism is a runtime property. Hence a runtime error. If you look after something that will trigger at compile time, you need static polymorphism.
template<typename Child>
struct Parent {
void callMe() {
static_cast<Child*>(this)->callMeImpl();
}
};
struct SomeChild : Parent<SomeChild> {
};
Now, if you try to call callMe form the parent that is extended by SomeChild, it will be a compile time error.
You can also hold pointer to the parent just like dynamic polymorphism, as the parent will call the child function
Is making it private the only choice?
No, that's not a choice at all since you can still access the method if it's public or protected in the base classes.
Other than implementing the method in the class and resorting to run-time failures, there's not a lot you can do. You could port the whole thing to templates and use static polymorphism which, with further trickey, you could contrive a compile-time failure in certain instances, but that could be design overkill.
I guess you could make it a normal virtual function instead of a pure virtual function like this:
virtual void method() { /* code */ }
If this function is not being used in another class, you will be able to catch that. For example you could warn yourself:
virtual void method() { error = true; } //or whatever
As others have said there is no way of enforcing this at compile time. If you are referring to a pointer to a base class there is no way the compiler can know if that pointer is referring to one of the derived classes that does implement this method or one that doesn't.
So the case will have to be handled at runtime. One option is to just throw an exception. Another option is to introduce a level of indirection so that you can ask your base class if it implements a certain function before you call it.
Say you have a Base class with three methods foo, bar and doit and some derived classes do not want to implement foo then you could split up the Base class into two base classes:
class Base1 {
public:
virtual void foo() = 0;
};
class Base2 {
public:
virtual void bar() = 0;
virtual void doit() = 0;
};
Then in places where you are currently using Base you instead use a BaseSource:
class BaseSource {
public:
virtual Base1* getBase1() = 0;
virtual Base2* getBase2() = 0;
};
where getBase1 and getBase2 can return nullptr if a BaseSource does not offer that interface:
class Derived : public BaseSource, public Base2 {
public:
// don't implement foo();
// Implemementation of Base2
void bar() override;
void doit() override;
Base1* getBase1() override { return nullptr; } // Doesn't implement Base1
Base2* getBase2() override { return this; }
};
int main() {
std::vector<std::unique_ptr<BaseSource>> objects;
objects.push_back(std::make_unique<Derived>());
for (auto& o : objects) {
auto b1 = o->getBase1();
if (b1)
b1->foo();
auto b2 = o->getBase2();
if (b2)
b2->bar();
}
}
Live demo.

Executing base function before continuing in derived function

I'm trying to solve a problem where I have some classes in which I need to do some common work and then a bunch of problem specific work and when this is finished do some more processing common to all these classes.
I have a Base and Derived class that both have a function called Execute. When I call the derived version of this function, I'd like to be able to do some processing common to all my derived classes in the Base and then continue executing in my Derived::Execute and going back to Base::Execute to finish off with some common work.
Is this possible in C++ and how would one best go about doing that?
This is the idea, however it's probably not very workable like this:
class Base
{
public:
virtual void Execute();
};
Base::Execute() {
// do some pre work
Derived::Execute(); //Possible????
// do some more common work...
}
class Derived : public Base
{
public:
void Execute();
};
void Derived::Execute()
{
Base::Execute();
//Do some derived specific work...
}
int main()
{
Base * b = new Derived();
b.Execute(); //Call derived, to call into base and back into derived then back into base
}
Use a pure virtual function from base..
class Base
{
public:
void Execute();
private:
virtual void _exec() = 0;
};
Base::Execute() {
// do some common pre work
// do derived specific work
_exec();
// do some more common work...
}
class Derived : public Base
{
private:
void _exec() {
// do stuff
}
};
int main()
{
Base * b = new Derived();
b.Execute();
}
EDIT: changed the flow slightly after reading the question some more.. :) The above mechanism should match exactly what you require now -
i.e.
Base Common Stuff
Derived specific stuff
Base Common stuff again
This is called the NVI (Non-Virtual Interface, from Herb Sutter here) idiom in C++, and basically says that you should not have public virtual functions, but rather protected/private virtual functions. User code will have to call your public non-virtual function in the base class, and that will dispatch through to the protected/private virtual method.
From a design perspective the rationale is that a base class has two different interfaces, on one side the user interface, determined by the public subset of the class, and on the other end the extensibility interface or how the class can be extended. By using NVI you are decoupling both interfaces and allowing greater control in the base class.
class base {
virtual void _foo(); // interface to extensions
public:
void foo() { // interface to users
// do some ops
_foo();
}
};
Turn the problem from its head to its feet. What you actually want to have is a base class algorithm that derived classes can plug into:
class Base {
public:
void Execute()
{
// do something
execute();
// do some more things
}
private:
virtual void execute() = 0;
};
class Derived : public Base {
public:
// whatever
private:
virtual void execute()
{
//do some fancy stuff
}
};
Letting derived classes plug into base class algorithms is often called "template method" pattern (which has nothing to do with template. Having no public virtual functions in the base class interface is often called "non-virtual interface" pattern.
I'm sure google can find you a lot on those two.
Move that Base::Execute internally in two functions and then use RAII to implement that easily.
class Base{
protected:
void PreExecute(){
// stuff before Derived::Execute
}
void PostExecute(){
// stuff after Derived::Execute
}
public:
virtual void Execute() = 0;
};
struct ScopedBaseExecute{
typedef void(Base::*base_func)();
ScopedBaseExecute(Base* p)
: ptr_(p)
{ ptr_->PreExecute() }
~ScopedBaseExecute()
{ ptr_->PostExecute(); }
Base* ptr_;
};
class Derived : public Base{
public:
void Execute{
ScopedBaseExecute exec(this);
// do whatever you want...
}
};

Overriding same method in only some child classes, how to avoid duplication?

I am using a base class and there are 5 child classes currently for it. Some of the functions are similar for 3 of the children but not all of them. I cannot introduce a new level of hierarchy as some methods are repeated in child 1,2,3 and some in 2,3,4.
How best can I avoid overriding the methods in all 3 children and repeating the code.
When you don't want to use multiple inheritance, you could also use composition.
Put the common code into one special class and add instances of the class to those subclasses which need the code. You then could either navigate to the functionality or wrap the call into access methods (inline).
Create a mix-in class and have the children with the method in common inherit from it also. For example:
class Base {
public:
virtual commonFunction() { /* default implementation */ };
};
class Mixin {
public:
virtual notSoCommonFunction() { /* default implementation */ };
};
class D1 : public Base {
public:
virtual commonFunction() { /* override implementation */ };
};
class D2 : public Base, public Mixin {
public:
virtual commonFunction() { /* override implementation */ };
virtual notSoCommonFunction() { /* override implementation */ };
};
class D3 : public Base, public Mixin {
public:
virtual commonFunction() { /* override implementation */ };
virtual notSoCommonFunction() { /* override implementation */ };
};
So all classes D1, D2, D3 implement (and optionally override) commonFunction, but only D2 and D3 implement (and optionally override notSoCommonFunction).
You could add a new intermediate class with protected methods for the different implementations of each function. Then in the child classes override the methods from the original base class and call the appropriate protected methods from this new intermediate class.
class Base {
public void foo() { /* ... */ }
public void bar() { /* ... */ }
}
class Middle extends Base {
protected void foo1() { /* ... */ }
protected void foo2() { /* ... */ }
protected void bar1() { /* ... */ }
protected void bar2() { /* ... */ }
}
class Child1 extends Middle {
// Use default foo()
public void bar() { bar1(); }
}
class Child2 extends Middle {
public void foo() { foo1(); }
public void bar() { bar2(); }
}
class Child3 extends Middle {
public void foo() { foo2(); }
// Use default bar()
}
Or you could explore Strategy pattern. Sometimes, HAS-A relation is better choice than IS-A. Of course, I don't know if your problem allows introduction of the pattern
Most of the answers above talk of using a new class, but the method I am using calls many other methods of the class and also uses some of the class instance variables. If I use a mixin or compose a new class, I wont be able to implement the method.
If you need access to the other members of the class, you could use templated mixins that static_cast the this pointer to the appropriate type:
template<class T>
class M1Mixin {
public:
int m1() {
return static_cast<T*>(this)->some_value;
}
};
class Base {
public:
int some_value;
...
};
class A : public Base, M1Mixin<A> {
...
};
It's not pretty, but it works.
The code review can wait before you get the satisfactory answer for this, right? Cool. :-)
Another solution that might work is the following:
Suppose that the base class is called MyBaseClass, the child classes are ChildClass1 through ChildClass5, and the function that you want to duplicate looks like this:
public int foo(Object args)
{...}
Now what you can do is create a separate class (call it "HelperFunctions" or some such) with a static method:
public static int fooHelper(BaseClass theClass, Object args)
{insert duplicated code here}
and then have the foo functions in the classes you want call that helper function.
This has a few advantages:
You're not creating new objects or changing the type hierarchy. Since the helper function is static you can call it without needing any new objects.
You can still call methods of the class, because you are passing in the object of type BaseClass, so you can call methods on it just like you would from within the class.
Most of the answers above talk of using a new class, but the method I am using calls many other methods of the class and also uses some of the class instance variables. If I use a mixin or compose a new class, I wont be able to implement the method.
I'm not sure I understand what the problem is. At least in my solution, you're passing in the object, so you can call whatever methods and access instance variables on the object you want. Is the problem that the instance variables or methods you want to access are private so you can't access them outside the class? In that case you can easily solve it by declaring the helper function to be a friend function (just google "c++ friend function" for tutorials on how to use them)