How to prevent call to base implementation of a method - c++

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.

Related

How to hide private base class members and methods from users

Maybe I didn't make my question clear, the following answers are not answering my question. Let me make the question more specific. My question is that I have a base class to send to clients so that clients can develop derived classes at their ends. How can I hide the private methods and members?
For example, in the following code snippets, the base.h file declares the base class which provides three private virtual methods for clients to override in the derived classes. The clients can override none, any, or all of them. Assuming a client developed a derived class called "Derived", and passed the "Derived" class creator to me so that I can create the Derived class somewhere, e.g. Base* p_base = new Derived() and call p_base->Execute() to actually call client implementations of virtual functions DoInitialize(), DoExecute(), DoCleanUp().
BTW: I don't think opaque pointers will work.
In Base.h file:
class Base {
public:
Base();
~Base();
void Execute();
private:
// virtual functions to be overridden by derived classes.
virtual void DoInitialize() {}
virtual void DoExecute() {}
virtual void DoCleanUp() {}
private:
// private members and functions that are intended to hide from clients
std::vector<float> data_;
....
}
In Base.cpp file
Base::Execute() {
DoInitialize();
DoExecute();
DoCleanUp();
}
In clients end
class Derived : public Base {
public:
Derived();
~Derived();
private:
// overide base class methods
void DoInitialize() {}
void DoExecute() {}
void DoCleanUp() {}
}
In my end somewhere:
void main() {
Base* p = DerivedCreater(); // creater a Derived class, assumes DerivedCreater() has passed in by clients.
p->Execute(); // I want to call the client implementation of DoInitialize(), DoExecute(), and DoCleanUp()
}
The way to go is to have an opaque pointer to the implementation.
class BaseImpl;
class Base {
public:
Base();
~Base();
private:
// virtual functions to be overridden by derived classes.
virtual void Initialize() {}
private:
// private members and functions that are not intended to override by derived classes
void Configure() { m_impl->Configure(); }
BaseImpl* m_impl;
}
Then, in the BaseImpl, you keep a pointer to the Base and you call the virtual functions as wanted. You keep BaseImpl.h in your private includes and you don't distribute it to the library users.
See:
https://en.cppreference.com/w/cpp/language/pimpl

Is there a way to force-invoke the overridden method?

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.

Pure interface of a class with subclasses

Lets suppose you want to make an interface of the class Derived and it looks like this:
class Derived : public Base
{
public:
foo();
}
class Base
{
public:
tii();
//many other methods
}
How would you do the Interface? How can you make Base::tii visible (and also other methods) to this new interface?
class IDerived
{
public:
virtual foo() = 0;
// should I declare here tii() as a pure virtual function?
// but by doing it now there is ambiguity!
}
What is a good strategy?
The new Derived class should look like this....
class Derived : public Base, public IDerived
{
//implement the real thing
}
Your example is doing things backwards: the interface should be defined independently of any concrete classes with all pure virtual methods:
class IDerived
{
public:
virtual void foo() = 0;
virtual ~IDerived() {} // don't forget to include a virtual destructor
}
And the concrete classes will derive publicly from the interface:
class Derived : public Base, public IDerived
{
public:
void foo();
}
If you want IDerived to also declare methods that Derived inherits from Base, you can have Derived explicitly implement the method by calling the inherited implementation:
class Derived : public Base, public IDerived
{
public:
void foo();
void bar() { Base::bar(); }
}
At front, I dislike interfaces (they are grown by other languages than c++).
Anyway, if you have one, it should be complete: Hence have the 'tii() as a pure virtual function'. To resolve the conflict rewrite that function in 'Derived' (forward to Base::tii).

virtual inheritance query

class Base {
public:
Base(){ }
virtual void Bfun1();
virtual void Bfun2();
};
class Derv : public Base {
public:
Derv(){ }
void Dfun1();
};
Is there a difference between above definitions and the below ones ? Are they same ? if not how both are the different functionally ?
class Base {
public:
Base(){ }
void Bfun1();
void Bfun2();
};
class Derv : public virtual Base {
public:
Derv(){ }
void Dfun1();
};
They are completely different. The first set defines Bfun1 and Bfun2 as virtual function, that allows overriding them in the derived class and call those in the derived class through a base class pointer:
// assume you've overridden the functions in Derived
Base* base_ptr = new Derived;
base_ptr->Bfun1(); // will call function in derived
The second set, however, they're just normal functions. Instead, you declared the base class to be virtual, which has many implications you best read about in a good C++ book or search through the SO questions, I think we have one on that topic.

A way to enforce use of interface in C++

In C++, let's say I have a class Derived that implements an interface class BaseInterface, where BaseInterface has only pure virtual functions and a virtual destructor:
class BaseInterface
{
public:
virtual void doSomething() = 0;
~BaseInterface(){}
};
class Derived : public BaseInterface
{
public:
Derived() {}
~Derived(){}
protected:
virtual void doSomething();
private:
int x;
};
No classes outside the Derived class hierarchy should call Derived::doSomething() directly, i.e., it should only be accessed polymorphically through the BaseInterface class. To enforce this rule, I have made Derived::doSomething() protected. This works well, but I'm looking for opinions pro/con regarding this approach.
Thanks!
Ken
I think you're looking for the non-virtual interface (NVI) pattern: a public non-virtual interface that calls a protected or private virtual implementation:
class BaseInterface
{
public:
virtual ~BaseInterface(){}
void doSomething() { doSomethingImpl(); }
protected:
virtual void doSomethingImpl() = 0;
};
class Derived : public BaseInterface
{
public:
Derived() {}
virtual ~Derived(){}
protected:
virtual void doSomethingImpl();
private:
int x;
};
If it is part of the interface, why would you not want users to call it? Note that as it is, they can call it: static_cast<BaseInterface&>(o).doSomething() is just an awkward way of saying o.doSomething(). What is the point of using the interface... if the object fulfills the interface, then you should be able to use it, or am I missing something?
Since you are not actually blocking anyone from calling the methods, I don't see a point in making the code more complex (both the class and users of the class) for no particular reason. Note that this is completely different from the Non-Virtual Interface in that in this idiom virtual functions are not accessible publicly (at any level) while in your case, the intention is allowing access, and making it cumbersome.
What you are doing is also mentioned in standard ISO/IEC 14882:2003(E) 11.6.1 and believe you are correct. Other than the fact, the member function isn't pure virtual in the given example. It should hold for pure virtual functions too, AFAIK.
The access rules (clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it.
[Example:
class B
{
public:
virtual int f();
};
class D : public B
{
private:
int f();
};
void f()
{
D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK: B::f() is public,
// D::f() is invoked
pd->f(); // error: D::f() is private
}
—end example]
Access is checked at the call point using the type of the expression used to denote the
object for which the member function is called (B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.
The key is the rest of your code. Only accept a BaseInterface* as an argument to any methods that require the doSomething() call. The client programmer is forced to derive from the interface to make his code compile.
This makes no sense to me. Regardless of which pointer you call doSomething(), you would still wind up with the method defined in most derived class. Consider the following scenario:
class BaseInterface
{
public:
virtual void doSomething() = 0;
~BaseInterface(){}
};
class Derived : public BaseInterface
{
public:
Derived() {}
~Derived(){}
virtual void doSomething(){}
private:
int x;
};
class SecondDerived : public Derived
{
public:
SecondDerived() {}
~SecondDerived(){}
private:
int x;
};
int main(int argc, char* argv[])
{
SecondDerived derived;
derived.doSomething(); //Derived::doSomething is called
BaseInterface* pInt = &derived;
pInt->doSomething(); //Derived::doSomething is called
return 0;
}