I am trying to define interface types in C++ using abstract classes and implement them with concrete classes. The problem I am running into is that I cannot both inherit and interface from another interface and inherit the implementation from a base concrete class.
My goal is to be able to define a hierarchy of interfaces which may inherit from less complex base interfaces. I also want to be able to extend the implementation of interfaces by inheriting from concrete classes (like inheriting from TObjectA in the example below).
This is what I have. The error I am getting is "object of abstract class type "TObjectB" is not allowed". I believe I know why, which is because I didn't implement MethodA() in TObjectB. But I really want is to have the implementation provided by a base class (TObjectA) and still have interface hierarchies (IInterfaceB inherits from IInterfaceA). I also don't want to repeat all the inherited interface methods in my derived concreate classes. How can I do this?
class IInterfaceA
{
public:
virtual void MethodA() = 0;
};
class IInterfaceB : IInterfaceA
{
public:
virtual void MethodB() = 0;
};
class TObjectA : public IInterfaceA
{
public:
void MethodA() { cout << "Method A"; }
};
class TObjectB : public TObjectA, public IInterfaceB
{
public:
void MethodB() { cout << "Method B"; }
};
void TestInterfaces()
{
IInterfaceB* b = new TObjectB(); // error: object of abstract class type "TObjectB" is not allowed
b->MethodB();
delete b;
}
In your class hierarchy, TObjectB actually has two IInterfaceA base class subobjects: one inherited through IInterfaceB and one inherited through TObjectA. The MethodA() from each of them needs to be implemented.
You need to inherit from the interface classes using public virtual inheritance, which ensures there is only a single base class subobject of each interface class type:
class IInterfaceA
{
public:
virtual void MethodA() = 0;
};
class IInterfaceB : public virtual IInterfaceA
{
public:
virtual void MethodB() = 0;
};
class TObjectA : public virtual IInterfaceA
{
public:
void MethodA() { cout << "Method A"; }
};
class TObjectB : public TObjectA, public virtual IInterfaceB
{
public:
void MethodB() { cout << "Method B"; }
};
void TestInterfaces()
{
TObjectB b_object;
IInterfaceB& b = b_object;
b.MethodB();
}
Whether or not such complex class hierarchies are desirable is another matter altogether.
Your problem is caused by the dreaded diamond inheritance. You've implemented TObjectA::IInterfaceA::MethodA but not IInterfaceB::IInterfaceA::MethodA.
My recommendation would be to make IIterfaceA and IIterfaceB completely independent. If that's not possible, you can look into virtual inheritance.
Related
I am still a bit new to object-oriented paradigm, and as such one thing about OOP clouds my mind. This may sound as a naive question with an obvious answer, and it may very well be one, but what are the differences between the following two cases:
case 1:
class A
{
public:
A() = default;
A(int i) : data_point(i) {};
virtual int process_data_point();
protected:
int data_point=0;
};
class B : public A
{
public:
int process_data_point() override;
};
case 2:
class A
{
int data_point=0;
public:
A() = default;
A(int i) : data_point(i) {};
int process_data_point();
};
class B
{
public:
A process_data_point_in_a_different_way();
A data_point
};
I mean, I know that case 1 deals with inheritance, that being in the spirit of OOP, but I cannot escape the feeling that one can also emulate inheritance by just taking the base class and defining the new class which contains data members of the base class, with some additional functionality (as sketched in case 2). I am aware that emulating inheritance on a long run may end up being too complex (especially if one ends up with having some unwanted functionality from data member class), but I would expect that for some simple cases inheritance emulation works just fine.
Can someone elaborate more pedagogically on this? Is the idea about emulation inherently bad one, or does it make sense in some cases?
Difference 1
Under "inheritance" subject there is another subject which called "polymorphism" - The ability to relate to different objects in the same way. When you use the inheritance way, you can make interface class, and in the future use it in polymorphism situation. Have a quick look on this code:
class BaseClass {
public:
virtual void action() = 0;
};
class A : public BaseClass {
public:
void action() {
cout << "A class" << endl;
}
};
class B : public BaseClass {
public:
void action() {
cout << "B class" << endl;
}
};
In this case, we have 3 classes. BaseClass that includes abstract function "action", and two inherit classes. The following "main" function show how to use them in polymorphism way:
int main() {
A a;
B b;
vector<BaseClass*> all = vector<BaseClass*>();
all.push_back(&a);
all.push_back(&b);
for (size_t i = 0; i < all.size(); i++) {
all[i]->action();
}
}
The output will be:
A class
B class
But look, I didn't call a.action() or b.action()- I called them both in a loop all[i]->action(). You can't do this without inheritance.
Difference 2
"Protected" privilege in classes give the access only for the class itself and the inherit classes. Let's have a look on another example:
class BaseClass {
private:
void private_method() {
cout << "Base class private method" << endl;
}
protected:
void protected_method() {
cout << "Base class protected method" << endl;
}
public:
void public_method() {
cout << "Base class public method" << endl;
}
};
Assume we have this class, which includes private_method, protected_method, and public_method. Now we have two different classes. The class A that inherit BaseClass and class B that include BaseClass. Let's see which methods we can use in each class:
class A : public BaseClass {
public:
void test_privileges() {
//this->private_method(); // Compilation error!
this->protected_method();
this->public_method();
}
};
class B {
private:
BaseClass bc;
public:
void test_privileges() {
//bc.private_method(); // Compilation error!
//bc.protected_method(); // Compilation error!
bc.public_method();
}
};
As you can see, there is a protection difference between inherit a class and includes it.
Difference 3
When you design a code, you want it to be as clear as possible to everyone. To do this, you have to keep on a logical flow inside your code. There is a logical difference between inherit a class an includes it.
When you are inherit a class you can say that the heiress class is the heritage class, for example:
class Animal {};
class Dog : public Animal {};
class Cat : public Animal {};
The Dog is an Animal -> So Dog class have to inherit the Animal class.
When you include a class inside another one, you can say: The contains class have the includes class, for example:
class Tail {};
class Eye {};
class Dog {
private:
Tail tail;
Eye eye;
};
The Dog have a tail. -> So Dog class contains Tail class.
The Dog have an eye. -> So Dog class contains Eye class.
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).
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.
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.
I have 6 classes which all perform the same actions. I would like to move common behavior to a common [base] class.
There are actions to be performed on 6 separate objects. The six objects are located in derived classes. Intuitively, the private member objects would be accessed through the child (derived class) in the base class.
What is the C++ pattern I am looking for?
class Base
{
// Common behavior, operate on m_object
...
void Foo()
{
m_object.Bar();
}
};
class Derived1 : public Base
{
// No methods, use Base methods
private:
MyObject1 m_object;
}
class Derived2 : public Base
{
// No methods, use Base methods
private:
MyObject2 m_object;
}
The thing that is boxing me into this situation is MyObject1, MyObject2, etc offer Bar(), but don't share a common base class. I really can't fix the derivation because the objects come from an external library.
If they are introduced in the derived classes, then the base class cannot directly access them. How would the base class know that all derived classes have a specific member?
You could use virtual protected methods like so:
class my_base
{
protected:
virtual int get_whatever();
virtual double get_whatever2();
private:
void process()
{
int y = get_whatever();
double x = get_whatever2();
//yay, profit?
}
}
class my_derived_1 : my_base
{
protected:
virtual int get_whatever()
{
return _my_integer;
}
virtual double get_whatever2()
{
return _my_double;
}
}
Another possibility (if you want to call the base methods from the derived classes) is to simply supply the arguments to the base methods.
class my_base
{
protected:
void handle_whatever(int & arg);
};
class my_derived : my_base
{
void do()
{
my_base::handle_whatever(member);
}
int member;
};
C++ does and doesn't. It has a very powerful multiple inheritance support, so there is no super keyword. Why? Imagine that your base class is, say, inherited by another two classes, or even is a part of virtual inheritance hierarchy. In that case you can't really tell what super is supposed to mean. On the other hand, there are virtual methods, you can always have them in base class and implement in derived classes (that's what languages like Java do, except that they they don't have multiple class inheritance support). If you don't want to go with polymorphism, you can use something like this:
#include <cstdio>
template <typename T>
struct Base
{
void foo ()
{
std::printf ("Base::foo\n");
static_cast<T *> (this)->bar ();
}
};
struct Derived : Base<Derived>
{
void bar ()
{
std::printf ("Derived::bar\n");
}
};
int
main ()
{
Derived d;
d.foo ();
}
This is an extremely simple example - you can extend the above example with access control, friends, compile-time assertions etcetera, but you get the idea.
Have you considered not using inheritance?
class FooBar
{
MyObject m_object;
public:
FooBar(MyObject m): m_object(m) {}
//operate on different m_objects all you want
};
What about deriving your six separate objects from a common base class? Then you can declare virtual methods in that base class to create your interface, and then implement them in the derived object classes.
Maybe you just need a template instead of superclass and 6 derived classes?
It seems that you need to access not the parent's, but child's field. You should do it by introducing an abstract method:
class ParentClass
{
public:
void f();
protected:
virtual int getSomething() = 0;
};
ParentClass::f()
{
cout << getSomething() << endl;
}
class DerivedClass : public ParentClass
{
protected:
virtual int getSomething();
}
DerivedClass::getSomething() { return 42; }
If you need to access parent's method, just use ParentClass::method(...):
class ParentClass
{
public:
virtual void f();
};
class DerivedClass : public ParentClass
{
public:
virtual void f();
};
void DerivedClass::f()
{
ParentClass::f();
}