Pure interface of a class with subclasses - c++

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).

Related

How to prevent call to base implementation of a method

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.

C++: How to implement function in a parent interface with a base class?

Consider following hierarchy:
class Interface {
public:
virtual void foo() = 0;
};
class SubInterface: public Interface {
public:
virtual void bar() = 0;
};
class Base: public Interface {
public:
void foo() {};
};
class Impl: public SubInterface, public Base {
public:
void bar() {};
};
There are several sub interfaces which offer other methods in addition to foo().
There can be several implementing classes to a sub interface.
foo() is always implemented the same way.
Here is an example which simulates how these classes would be used:
int main() {
SubInterface* view1 = new Impl(); // Error! Interface::foo() is pure virtual within Impl
view1->foo();
view1->bar();
Interface* view2 = view1;
view2->foo();
}
Why can't the compiler see that Interface::foo() is implemented in Base which Impl inherits from?
I figured that I could implement foo() in Impl explicitly and delegate the call to Base like this:
class Impl: public SubInterface, public Base {
public:
void foo() {
Base::foo();
}
void bar() {};
};
However, I would have to do that for all classes which implement a sub interface, so this way isn't exactly ideal. Is there a better solution?
SubInterface and Base should inherit virtually from Interface otherwise you are creating ambiguity in form of the dreaded diamond
Basically, what happens is that Impl contains two 'instances' of Interface.
Here is why - follow the diagram:

Abstract interface inheritance

Must virtual methods be always implemented in derived class?
Can I write something like this?
<!-- language: lang-cpp -->
class BaseInterface
{
public:
virtual void fun_a() = 0;
virtual void fun_b() = 0;
virtual ~BaseInterface();
};
class Derived : public BaseInterface
{
void fun_a() { ... };
};
class FinalClass : public Derived
{
void fun_b() { ... };
}
int main()
{
FinalClass test_obj;
test_obj.fun_a(); // use Derived implementation or fail ???
test_obj.fun_b(); // use own implementation
BaseInterface* test_interface = new FinalClass();
test_interface->fun_a(); // fail or ok ???
test_interface->fun_b();
}
Is the code above correct?
Does another virtual method outflank exist?
Pure virtual methods always must be reimplemented in derived class?
Actually a derived class which is going to be instantiated.
In your code, you didn't make an object from Derived so it's OK.
Can i write something like this?
Yes.
You had some minor errors that I corrected them:
class BaseInterface
{
public:
virtual void fun_a() = 0;
virtual void fun_b() = 0;
virtual ~BaseInterface() {}; // You forget this
};
class Derived : public BaseInterface
{
public:
void fun_a() {} // This should be public as its base
};
class FinalClass : public Derived
{
public:
void fun_b() {} // This should be public as its base
};
int main()
{
FinalClass test_obj;
test_obj.fun_a();
test_obj.fun_b();
BaseInterface* test_interface = new FinalClass();
test_interface->fun_a();
test_interface->fun_b();
}
It makes Derived also an abstract class which you cannot instantiate, seeing you don't implement all the virtual functions from it's base, it becomes an abstract class you cannot directly instantiate.
See here: liveworkspace.org/code/6huYU$10
For the rest, your code should work.
Code is correct.
There is no special concept for interface in C++. All are classes. Some of the class methods can be pure virtual. It only means that compiler cannot create an instance of such class.

Multiple inheritance conflict

I have the following code:
class Interface
{
virtual void method()=0;
};
class Base : public Interface
{
virtual void method()
{
//implementation here
}
};
class Parent: public Interface
{
};
class Child : public Base, public Parent
{
};
int main()
{
Child c;//ERROR: cannot instantiate abstract class
}
Now I know why this is happening, since I'm inheriting Parent then I have to implement method again. But it's already defined in Base class and I don't want to override that definition for every child class. I think there was some standard way of getting rid of this in c++ (telling compiler which copy of Interface should it use) I just can't remember what it was.
What you are talking about is called dominance.
From the linked article:
class Parent
{
public:
virtual void function();
};
class Child1 : public virtual Parent
{
public:
void function();
};
class Child2 : public virtual Parent
{
};
class Grandchild : public Child1, public Child2
{
public:
Grandchild()
{
function();
}
};
You have a diamond-shaped hierarchy but are not using virtual inheritance.
As a result, you end up with two distinct virtual method() functions in your Child class.
One way to fix it is to move to using virtual inheritance. This way you'll only have a single Child::method() and won't need two implementations.
Pure virtual functions must be defined in the derived class.
If you don't do so, your derived class (in this case "child") will itself become an abstract class which can't be instantiated and hence the error.

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.