I have a Class "Parent1" and another "Parent2", which symbolize different hardware implementations of a device "Subclass". What is the most elegant way of implementing this? I have thought about using templates e.g.
class Parent1{
public:
Parent1():
void run();
};
class Parent2{
public:
Parent2():
void run();
};
template<typename Parent>
class Subclass : Parent {
public:
Subclass();
void doSomething(){Parent:run();}
}:
But then the Subclass does not know the run() function from the base class.
I also thought about making the Subclass an interface class with the methods that the Subclass needs to inherit from the Parents being pure virtual functions that are then specified in a further subclass that inherits from the chosen class.
I believe this could be ok for this particular application since there is not a huge number of methods I would need to virtualize but I am wondering if that would scale. So my solution would look like this.
class Subclass {
public:
Subclass();
virtual void run()=0;
void doSomething(){run();}
}:
class SubSubclass1 : Subclass, Parent1{
public:
SubSubclass1():Subclass(),Parent1(){}
void run(){Parent1:run();}
};
class SubSubclass2 : Subclass, Parent2{
public:
SubSubclass2():Subclass(),Parent2(){}
void run(){Parent2:run();}
};
but I would like to know if there is a better way of doing this?
Thanks a ton!
Why not just implement a base interface class for the two "Parents"?
class IBase
{
virtual ~IBase();
virtual void run();
};
class Parent1 : public IBase
{
public:
Parent1();
void run(); // implement
};
class Parent2 : public IBase
{
public:
Parent2();
void run(); // implement
};
Then you can use an IBase pointer to point at the actual "Parent" object.
Update:
Example to use this
int main()
{
Parent1 p1;
Parent2 p2;
IBase* basePtr;
basePtr = &p1;
basePtr->run(); // runs Parent1::run() for p1
basePtr = &p2;
basePtr->run(); // runs Parent2::run() for p2
return 0;
}
Related
I have an abstract base class with one purely virtual method:
class Base
{
public:
virtual void update() = 0;
};
Is there any way I could create a class that inherits from Base, overrides the update method, but still forces its children to implement an update method? Like this:
class Base2 : public Base
{
public:
void update() override
{
if(bSomeCondition)
{
update(); //Calls child's update method
}
}
virtual void update() = 0; // Obviously not like this
};
I know I could create two new purely virtual methods with slightly different names in Base2, and just override those in child classes, but I would really like to keep these method names if that would be possible.
I'm guessing this isn't possible?
You can provide a definition for a pure virtual function, just not inline.
class Base2 : public Base
{
public:
void update() override = 0;
};
void Base2::update() // Base2 is abstract regardless of this
{
if(bSomeCondition)
{
update();
}
}
However, this is not useful with the current implementation of Base2::update. Because a child class must override it anyway, Base2 version will not be called unless used explicitly:
class Child: public Base2
{
public:
void update() override
{
Base2::update(); //infinite recursion with such implementation
}
};
// the other way would be to require calling it explicitly at call site
std::unique_ptr<Base2> ptr = std::make_unique<Child>();
ptr->Base2::update();
What you should do is to provide an implementation and another pure virtual function (possibly protected) to be called:
class Base2 : public Base
{
public:
void update() override;
protected:
virtual void doStuff() = 0;
};
void Base2::update()
{
if(bSomeCondition)
{
doStuff(); //Calls child's update method
}
}
No, it is not possible and in my opinion it would be very illegible.
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:
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.
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.