I have a top API (based on abstract class) which is composed by a base API (that will be reused by different top APIs).
class api_base {
public:
virtual int foo() = 0;
};
class api_top : public api_base {
public:
virtual int bar() = 0;
}
Then, I want to provide a base implementation for base API:
class imp_base {
public:
int foo() { return 1; }
}
And finally implement top API using base implementation for those functions defined in base API:
class imp_top : public api_top, public imp_base {
public:
int bar() { return 1; }
}
When I instantiate an object of imp_top type, compiler say that foo() function is not implemented. But that is not true, since imp_top derives from imp_base, which do have foo() function implemented.
Any advice about this?
Thank you in advance.
Full test code:
#include <stdio.h>
class api_base {
public:
virtual int foo() = 0;
};
class api_top : public api_base {
public:
virtual int bar() = 0;
};
class imp_base {
public:
int foo() { printf("foo from imp_base\n"); }
};
class imp_top : public api_top, public imp_base {
public:
int bar() { printf("bar from imp_top\n"); }
};
int main()
{
printf("Hello\n");
imp_top a;
a.bar();
a.foo();
return 1;
}
Compiler result:
test.cpp:26:12: error: cannot declare variable ‘a’ to be of abstract type ‘imp_top’
imp_top a;
^
test.cpp:18:7: note: because the following virtual functions are pure within ‘imp_top’:
class imp_top : public api_top, public imp_base {
^
test.cpp:5:17: note: virtual int api_base::foo()
virtual int foo() = 0;
^
test.cpp:29:6: error: request for member ‘foo’ is ambiguous
a.foo();
^
test.cpp:15:9: note: candidates are: int imp_base::foo()
int foo() { printf("foo from imp_base\n"); }
^
test.cpp:5:17: note: virtual int api_base::foo()
virtual int foo() = 0;
First Always use override keyword when redefining the functions in child classes.
Second read about virtual inheritance.
The following works :
class api_base {
public:
virtual int foo() = 0;
};
class api_top : public virtual api_base {
public:
virtual int bar() = 0;
};
class imp_base : public virtual api_base {
public:
int foo() override { printf("foo from imp_base\n"); return 0; }
};
class imp_top : public api_top, public imp_base {
public:
int bar() override { printf("bar from imp_top\n"); return 0; }
};
int main(){
imp_top a;
a.bar();
a.foo();
return 1;
}
Change:
class api_top : public api_base to class api_top : public virtual api_base
and:
class imp_base to class imp_base : public virtual api_base
Then it works.
To understand this, see: virtual inheritance. And yes (just saw Ext3h's post), use the override keyword.
You should have used the override keyword, then you would had noticed that you did not implement the interface but defined an entirely new foo() method.
You will need to derive both imp_base and api_top from api_base by virtual inheritance.
Related
I'm trying to inherit from a hierarchy of abstract base classes, using an equivalent hierarchies of implementation classes. The only way I've figured out how to do it is using virtual inheritance.
/* Foo Interface */
class IFoo
{
public:
virtual void foo() = 0;
virtual ~IFoo() = default;
};
/* Bar Interface */
class IBar : virtual public IFoo
{
public:
virtual void bar() = 0;
virtual ~IBar() = default;
};
/* A specialized Foo */
class SpecificFoo : virtual public IFoo
{
public:
void foo() override { std::cout << "Foo!\n"; }
};
/* A specialized Bar */
class SpecificBar : virtual public IBar, virtual public SpecificFoo
{
public:
void bar() override { std::cout << "Bar!\n"; }
};
int main()
{
SpecificBar b;
b.bar();
return 0;
}
Although I'm not entirely opposed to using virtual inheritance, I'm not sure that it's the correct approach. Having to use dynamic_cast seems like something to avoid if possible. Is there a better way to do this?
I've tried something with an adapter pattern, but copy/pasting wrapper methods is getting out of hand.
I don't see the benefit of making IBar a sub-type of IFoo from the posted code.
IMO, it will be better to remove that inheritance.
/* Foo Interface */
class IFoo
{
public:
virtual void foo() = 0;
virtual ~IFoo() = default;
};
/* Bar Interface */
class IBar
{
public:
virtual void bar() = 0;
virtual ~IBar() = default;
};
/* A specialized Foo */
class SpecificFoo : public IFoo
{
public:
void foo() override { std::cout << "Foo!\n"; }
};
/* A specialized Bar */
class SpecificBar : public IBar
{
public:
void bar() override { std::cout << "Bar!\n"; }
};
/* A specialized Foo and Bar */
class SpecificFooAndBar : public IFoo, public IBar
{
public:
void foo() override { std::cout << "Foo!\n"; }
void bar() override { std::cout << "Bar!\n"; }
};
I came up with a solution that avoids virtual inheritance, but also gets rid of code duplication. I used a template parameter to specify the base class.
/* Foo Interface */
class IFoo
{
public:
virtual void foo() = 0;
virtual ~IFoo() = default;
};
/* Bar Interface */
class IBar : public IFoo
{
public:
virtual void bar() = 0;
virtual ~IBar() = default;
};
/* A specialized Foo */
template <typename _BaseClass>
class SpecificFooTpl : public _BaseClass
{
public:
void foo() override { std::cout << "Foo!\n"; }
};
using SpecificFoo = SpecificFooTpl<IFoo>;
/* A specialized Bar */
class SpecificBar : public SpecificFooTpl<IBar>
{
public:
void bar() override { std::cout << "Bar!\n"; }
};
int main()
{
SpecificFoo f;
SpecificBar b;
f.foo();
b.bar();
return 0;
}
For code below, are there any other ways to access a method in base through interface?
struct Base {
void funct_base() {
printf("Common function for class Foo and class Bar\n");
}
};
struct IFoo {
virtual ~IFoo() {}
virtual void funct_a() = 0;
// would like to access Base::bunct_base() from here
};
struct Foo : public Base, public IFoo {
virtual void funct_a() {
printf("I am Foo:: funct A\n");
}
};
class IBar {
virtual ~IBar() {}
virtual void funct_a() = 0;
// would like to access Base::bunct_base() from here
};
class Bar : public Base, public IBar {
virtual void funct_a() {
printf("I am Bar:: funct A\n");
}
};
I know this can be done, but I just do not like the wrapper, it does not seem clean:
struct IBar {
virtual ~IBar() {}
virtual void funct_a() = 0;
virtual void funct_base() = 0;
};
struct Bar : public Base {
virtual void funct_a() {
printf("I am Bar:: funct A\n");
}
virtual void funct_base() {
Base::funct_base();
}
};
EDIT:
The question is, there is one base class, and two different derived classes that inherit from the same base class. Is there a way to access a base class method through derived class interface without adding a base class method wrapper?
Use a abstract base class IBase with a Abstract method funct_base and make the interface class a Virtual base classes of the classes Base, IFoo and IBar:
struct IBase {
virtual void funct_base() = 0;
};
struct Base : public virtual IBase {
virtual void funct_base() override { printf("Common function for class Foo and class Bar\n"); }
};
struct IFoo : public virtual IBase {
virtual void funct_a() = 0;
};
struct Foo : public IFoo, public Base {
virtual void funct_a() override { printf("I am Foo:: funct A\n"); }
};
class IBar : public virtual IBase {
virtual void funct_a() = 0;
};
class Bar : public IBar, public Base {
virtual void funct_a() override { printf("I am Bar:: funct A\n"); }
};
I have 3 interface (pure virtual) classes like this
class A {
virtual void M1() = 0;
virtual void M2() = 0;
};
class B : public A {
virtual void M3() = 0;
};
class C : public A {
virtual void M4() = 0;
};
I have the implementers like this
class Aimpl : A {
void M1 () override {};
void M2 () override {};
}
class Bimpl: public Aimpl, public B{
void M3() override {};
}
class Cimpl: public Aimpl, public C{
void M4() override {};
}
and
Bimpl b = Bimpl();
b.M2() // Error. M2 is ambigous. Can be from Aimpl or A
what's a simple way to fix this? I want to be able to pass around B or C in functions rather than Bimpl
Essentially, you have two different M2 methods in Bimpl: Aimpl::M2 and B::M2. You have run into the diamond-inheritance problem.
To fix it, you should use virtual inheritance. This question provides a very good overview. Essentially, you should use something like this:
class A {
virtual void M1() = 0;
virtual void M2() = 0;
};
class B : public virtual A {
virtual void M3() = 0;
};
class C : public virtual A {
virtual void M4() = 0;
};
class Aimpl : public virtual A {
void M1 () override {};
void M2 () override {};
};
class Bimpl: public virtual Aimpl, public virtual B {
void M3() override {};
};
class Cimpl: public virtual Aimpl, public virtual C {
void M4() override {};
};
Note that I'm not super super familiar with virtual inheritance, so this may or may not be the best way to apply virtual inheritance.
So I have two classes. One has only purely virtual functions. THe other implements those functions and is derived from the first class.
I get that i cant instantiate the first class. But when I try to create an object of the second class it fails as well.
This is how my second class looks in general:
class SecondClass : public FirstClass
{
public:
SecondClass();
virtual ~SecondClass(void);
void Foo();
void Bar();
}
Implementation:
SecondClass::SecondClass()
{...}
SecondClass::~SecondClass(void)
{...}
void SecondClass::Foo()
{...}
void SecondClass::Bar()
{...}
This how I instantiate it and get the Error:
SecondClass mSecClass;
Where am I going wrong here?
FirstClass.h
class FirstClass
{
public:
FirstClass(void);
virtual ~FirstClass(void);
virtual void Foo() = 0;
virtual void Bar() = 0;
};
You need to define the ~FirstClass() destructor and leave out its constructor
class FirstClass
{
public:
virtual ~FirstClass(void) {} // or use C++11 = default syntax
virtual void Foo() = 0;
virtual void Bar() = 0;
};
class SecondClass : public FirstClass
{
public:
SecondClass();
virtual ~SecondClass(void);
void Foo();
void Bar();
};
SecondClass::SecondClass() {}
SecondClass::~SecondClass(void) {}
void SecondClass::Foo() {}
void SecondClass::Bar() {}
int main()
{
SecondClass mSecClass;
}
Live Example.
Define every function you declare, except for pure virtuals(virtual void foo() = 0).
try the below code:
#include<iostream>
using namespace std;
class FirstClass
{
public:
FirstClass()
{
//
}
virtual ~FirstClass();
virtual void Foo();
virtual void Bar();
};
FirstClass::~FirstClass()
{
//
}
void FirstClass::Foo()
{
//
}
void FirstClass::Bar()
{
//
}
class SecondClass : public FirstClass
{
public:
SecondClass();
virtual ~SecondClass(void);
void Foo();
void Bar();
};
SecondClass::SecondClass(){
//
}
SecondClass::~SecondClass(void)
{//
}
void SecondClass::Foo()
{//
}
void SecondClass::Bar()
{//
}
int main()
{
SecondClass name;
return 0;
}
I'm getting a compile error when I try to compile my code.
The error is this:
multi.cc: In function ‘int main()’:
multi.cc:35: error: cannot declare variable ‘mdc’ to be of abstract type ‘MostDerivedClass’
multi.cc:27: note: because the following virtual functions are pure within ‘MostDerivedClass’:
multi.cc:13: note: virtual int Interface2::common_func()
multi.cc:36: error: request for member ‘common_func’ is ambiguous
multi.cc:13: error: candidates are: virtual int Interface2::common_func()
multi.cc:21: error: virtual int InterimClass::common_func()
And here is my code:
class Interface1 {
public:
virtual int common_func() = 0;
virtual ~Interface1() {};
};
class Interface2 {
public:
virtual int common_func() = 0;
virtual int new_func() = 0;
virtual ~Interface2() {};
};
class InterimClass : public Interface1 {
public:
virtual int common_func() {
return 10;
}
};
class MostDerivedClass : public InterimClass, public Interface2 {
public:
virtual int new_func() {
return 20;
}
};
int main() {
MostDerivedClass mdc;
int x = mdc.common_func();
cout << "The value = " << x << endl;
Interface2 &subset_of_funcs = dynamic_cast<Interface2 &>(mdc);
x = subset_of_funcs.common_func();
}
My questions:
How do I tell the compiler that common_func() is already implemented by the InterimClass which is a base class of MostDerivedClass?
Is there another way to fix my problem? What I would really like to do is to be able to also call common_func from Interface2. I'm working with some legacy code with a huge amount of methods in Interface1. In my new code, I only want to call a small set of these Interface1 functions, plus a few that I need to add.
You need to define a common_func() anyway in MostDerivedClass to satisfy your inheritance from Interface2
you can try something like
virtual int common_func() {
return InterimClass::common_func();
}
This is most useful if you cannot change the first Interface1
If you want a real inheritance relationship between your classes you need to follow Lol4t0 advice. Extract a superclass from Interface1, and make Interface2 subclass of this newly created class. Example :
class RootInterface{
public :
virtual int common_func() = 0;
virtual ~RootInterface(){}
};
class Interface1 : public virtual RootInterface{
public:
virtual ~Interface1() {};
};
class Interface2 : public virtual RootInterface{
public:
virtual int new_func() = 0;
virtual ~Interface2() {};
};
class InterimClass : public Interface1 {
public:
virtual int common_func() {
return 10;
}
};
class MostDerivedClass : public InterimClass, public Interface2 {
public:
virtual int new_func() {
return 20;
}
};
Add an override in MostDerivedClass, and from it call InterimClass::common_func().
First of all, I don't really understand the sense of your code.
You need to know that only Interface1::common_func is implemented.
Why don't you make Interface2 inherit from Interface1? I guess you want for both common_func methods to be equal.
Example code (uses polymorphism):
class Interface1
{
public:
virtual int common_func() = 0;
virtual ~Interface1() {};
};
class Interface2 : public Interface1 {
public:
virtual int common_func() = 0;
virtual int new_func() = 0;
virtual ~Interface2() {};
};
class InterimClass : public Interface2 {
public:
virtual int common_func() {
return 10;
}
};
class MostDerivedClass : public InterimClass {
public:
virtual int new_func() {
return 20;
}
};
int test_func()
{
Interface1 * i1 = new MostDerivedClass;
int x = i1->common_func();
cout << "The value = " << x << endl;
Interface2 * i2 = new MostDerivedClass;
x = i2->common_func();
return 0;
}
Let the second interface be derived from the first interface, remove the declaration of virtual int common_func() = 0; from the second interface, & use the keyword virtual to guide the compiler to the implementation.
class Interface1 {
public:
virtual int common_func() = 0;
virtual ~Interface1() {};
};
class BaseClass : public virtual Interface1 {
public:
virtual int common_func() {
return 10;
}
};
class Interface2 : public virtual Interface1{
public:
virtual int new_func() = 0;
virtual ~Interface2() {};
};
class DerivedClass : public virtual BaseClass, public virtual Interface2 {
public:
virtual int new_func() {
return 20;
}
};