I've got the following class structure:
class Common {
//members and data here.
};
class Derived1 : public Common
{
};
class Derived2: public Common, public Derived1
{
};
As I understand this hierarchy both Derived1 and Derived2 will share any members from Common.
Is there a way with out making Derived1 private in Derived2 to allow Derived2 to still inherit from Common but have separate function overrides.
Basically i need to override a virtual function in Derived1, and Derived2 but still have Derived1's function run (it's a threading api).
Any help apreciated.
As #Walkerneo points out, you don't need to inherit from both Common and Derived1. You can simply inherit from Derived1 and you'll also get inheritance from Common. You can explicitly call Derived1's method from Derived2's method by doing the following:
void Derived2::overriddenMethod ()
{
// Do something unique here
Derived1::overriddenMethod ();
// Maybe do some more stuff
}
You can achieve this even with single inheritance:
struct Base
{
virtual void foo() = 0;
virtual ~Base() { }
};
struct Intermediate : Base
{
virtual void foo() { /* ... */ }
// ...
};
struct Derived : Intermediate
{
virtual void foo()
{
Intermediate::foo();
// new stuff
}
};
Have you tried using virtual functions for runtime polymorphism and assigning a variable of your Derived2 class to a pointer of Derived1 class
class Common {
//members and data here.
public:
virtual void commonFunction() = 0; //keeping it pure virtual
};
class Derived1 : public Common
{
virtual void commonFunction(){
//do something in derived1
}
};
class Derived2: public Common, public Derived1
{
void commonFunction(){
//do something in derived2
}
};
int main(){
Derived2 derived2;
Derived1 *derived1;
derived1 = &derived2;
derived1->commonFunction(); //calls the common function definition in Derived1
/* ... */
}
Related
I have a abstract base class . There are many abstract classes which derived from this Abstract Base class
#if ABI_VERSION_ATLEAST1
class Base
{
public:
virtual void food() =0
};
#endif
for example
#if ABI_VERSION_ATLEAST1
class Derived1: public Base
{
};
#endif
Suppose i want to add new method to it, without breaking binary compatibility.
The only way is to extend this class
#if ABI_VERSION_ATLEAST2
class Base_Ext : public Base
{
public:
virtual void food1()=0;
};
#endif
The problem is the already existing derived classes implementation wont be able to access this food1().
How to solve this problem How can Abstract Derived classes see this new method
One solution i have in mind is : -
i would need to extend Derived1.......
#if ABI_VERSION_ATLEAST2
class Derived2 : public Derived1, public Base_Ex
{
} ;
#endif
again here to solve diamond problem, I will have to change
class Derived1: public Base to
class Derived1: public virtual Base {}
which i dont want to do.. as it would again break binary compatibility of existing derived classes.so stuck at it
You can create the second base class, let's name it OtherBase where you can add new methods.
And you can create new derived class, let's name it Derived2, which inherits methods from OtherBase and Derived1:
#include <iostream>
class Base
{
public:
virtual void food() = 0;
virtual ~Base() {}; // virtual destructor is necessary to avoid memory leak
};
class Derived1 : public Base
{
public:
virtual void food() override
{
std::cout << "Derived1::food" << std::endl;
}
virtual ~Derived1() override {}
};
class OtherBase
{
public:
virtual void food1() = 0;
virtual ~OtherBase() {}; // virtual destructor is necessary to avoid memory leak
};
class Derived2 : public OtherBase, public Derived1
{
public:
virtual void food1() override
{
std::cout << "Derived2::food1" << std::endl;
}
virtual ~Derived2() override {}
};
int main()
{
std::cout << "On the stack:" << std::endl;
Derived2 derived2;
derived2.food();
derived2.food1();
std::cout << "On the heap:" << std::endl;
OtherBase * otherBase_p1 = new Derived2();
if (otherBase_p1) // check if memory was is allocated
{
otherBase_p1->food1();
Base * base_p = dynamic_cast<Base *>(otherBase_p1);
if (base_p) // if dynamic_cast was unsuccessful than base_p is nullptr
{
base_p->food();
}
delete otherBase_p1;
}
}
I have the following code.
#include <iostream>
class Base1
{
public:
void print(){std::cout<<"Printing Base1\n";}
};
class Derived1: public Base1
{
public:
void print_1(){std::cout<<"Printing Derived1 \n";}
};
class Base2
{
public:
void myFunction1( Base1& b1)
{
myFunction2(b1);
}
virtual void myFunction2( Base1& b1)
{
b1.print();
}
};
class Derived2: public Base2
{
public:
void myFunction2( Derived1& d1)
{
d1.print_1();
}
};
int main()
{
Base1 b1;
Derived1 d1;
Base2 b2;
Derived2 d2;
b2.myFunction1(b1);
d2.myFunction1(d1);
return 0;
}
It results in the following output:
Printing Base1
Printing Base1
I thought of getting the following output
Printing Base1
Printing Derived1
One of the ways to get the desired output is to do the following.
class Derived2: public Base2
{
public:
void myFunction2( Base1& b1)
{
Derived1* d1 = static_cast<Derived1*> (&b1);
d1.print_1();
}
};
I would like to allow Derived2 to only deal with Derived1 and not with Base1. Otherwise, Some user may call Derived2::myFunction2 with Base1 object which can crash the program in such cases.
Is there a good solution?
myFunction2() in Derived2 does not override myFunction2() in Base2.
A virtual function gets overridden only if its signature matches, exactly. The function in this derived class takes a different parameter than the one in the base class. Hence, it does not override.
You have to make it override, as your first step.
class Derived2: public Base2
{
public:
void myFunction2( Base1& d1) override;
};
Now it's overridden. If you explicitly specified the override qualifier, as I did here, your compiler would've yelled at you already.
Now, your goal is to have whatever myFunction2 does, only have it take in effect for Derived1 class, and for all other Base1 classes, use what the superclass does.
Ok. This will require a little bit more work, and it will be slightly difficult to follow along. What needs to happen is another virtual inheritance, in Base1 this time:
class Derived2: public Base2
{
public:
void myFunction2( Base1& d1) override
{
d1.print_from_Derived2( *this );
}
};
Now, you need to define Base1::printDerived2(), which will invoke print(), which is what should happen in this case, according to your question:
class Base1
{
public:
virtual void print_from_Derived2( Derived2 &)
{
print();
}
};
And now, override it in Derived1 in order to put the last piece of the puzzle together:
class Derived1 : public Base1
{
public:
void print_from_Derived2( Derived2 &) override
{
// Do whatever print() from Derived2 needs to do, for
// this object, which is Derived1.
}
};
And here, you will do whatever needs to be done for Derived2 to print only Derived1. It's a bit of a circuitous route, but you finally reached the place where both actors are Derived1 and Derived2, without breaking any rules, and without any ugly casts.
You will need to do a bunch of forward declarations here, in order to stitch together all of these moving pieces. My examples are just brief simplifications, and they obviously have mutual references to each one, and will have to be broken apart into separate declarations and definitions, with appropriate forward declarations.
My question is, if I have something like
class Base {
...
public:
virtual void func();
}
void Base::func() {
//Implementation # 1
}
class Derived1 : public Base {
...
public:
void func();
}
void Derived1::func() {
//Implementation # 1
}
class Derived2 : public Base {
...
public:
void func();
}
void Derived2::func()
//Implementation # 1
}
class Derived3 : public Base {
...
public:
void func();
}
void Derived3::func() {
//Implementation # 2
}
What I'm trying to do is I want Derived1 and Derived2 to use the implementation of func() that was used in Base, but I want Derived3 to use func() a little differently. The problem is, if I make func() virtual in Base, then both Derived1 and Derived2 will need to implement it differently which I don't want. However, if I don't make it virtual, then all derived classes will have the same implantation for func(). How can I get past this problem?
A virtual function does not have to be overridden. Derived1 and Derived2 can just not redeclare func().
Only a pure virtual function (declared with = 0) must be overridden by (non-abstract) derived classes.
Edit
This will work, but unless you need more work done in the function, #Cameron's answer is the correct one.
You can call the base function from the derived function like so:
class Base
{
public:
virtual void foo() { /* Do something */ };
};
class Derived1 : public Base
{
public:
virtual void foo() { /* Do something else */ };
};
class Derived2 : public Base
{
public:
virtual void foo() { Base::foo(); /* Do something */ };
};
Have you thought to define as virtual func only in derived1 ?
The code that follows works like that ( is that what you intended ? )
#include <stdio.h>
#define X
class Base {
public:
void func();
};
void Base::func() {
printf("Base\n");
}
class Derived1 : public Base {
public:
virtual void func();
};
void Derived1::func() {
printf("derived1\n");
};
class Derived2 : public Base {
public:
};
class Derived3 : public Base {
public:
};
int main(int argc, char **argv)
{
Base b;
Derived1 d1;
Derived2 d2;
Derived3 d3;
b.func();
d1.func();
d2.func();
d3.func();
printf("hello world\n");
return 0;
}
Just call inside the func() of Derived1 and Derived2 the Base func() like this
Base::func();
Derived3 func() can have a different implementation.
I have a quite special situation in my C++ program.
Look at the following class setup:
class Base1 {
public: void baseMethod();
}
class Base2 : public Base1 {
...
}
class Common {
public: void commonMethod();
}
class Derived1 : public Base1, public Common {
...
}
class Derived2 : public Base2, public Common {
...
}
Base1 and Base2 are unchangeable for me as they are part of a library.
What I want to achieve is that both Derived1 and Derived2 share the same method commonMethod(), so I use class Common with that method as a common base for Derived1 and Derived2.
The problem now is that commonMethod() shall contain a call to baseMethod() which is defined in Base1! In the context of a Derived1- or Derived2-object this is legal, but how to define that method in Common?
I know that if I would declare Base2 as virtual derived class from Base1 and the same for Common, it shouldn't be a problem (at least for Derived2, not sure about Derived1). But as I can't modify Base2 that's not possible anyway.
Also letting Common inherit from Base2 and then Derived1 and Derived2 solely from Common doesn't work because I don't want Derived1 to inherit from Base2!
What then came to my mind was to make a dynamic_cast within commonMethod():
void Common::commonMethod() {
...
Base1* self = dynamic_cast<Base1*>(this);
if(self) {
self->baseMethod();
}
...
}
This seems to work, but I'm not sure if this is a "nice" solution...
Do you have any ideas how to make it better? Or do you think this solution isn't bad at all? :)
If the only purpose of Common is to provide a common implementation of that one method, you can use the CRTP pattern and template it on the type of the base. At this point you could decide whether it makes sense to keep it as multiple bases of the DerivedX types or it could make sense to linearize the inheritance hierarchy:
// Option1
template <typename Derived>
struct Common {
void commonFunction() { ... static_cast<Derived*>(this)->foo(); ... }
};
struct Derived1 : Base1, Common<Derived1>
// Option2 (not strictly CRTP, but close)
template <typename Base>
struct Common : Base {
void commonFunction() { ... this->foo(); ... } // keep the this-> here
};
struct Derived1 : Common<Base1>
If I were you, I'd choose composition over multiple inheritance, i.e. to define common as a member object of derived classes.
class Base1 {
public: void baseMethod();
}
class Base2 : public Base1 {}
class Common {
public:
Common(Base1 *base): m_base(base) {}
void Common::commonMethod()
{
m_base->baseMethod();
}
private:
Base1 *m_base;
}
class Derived1 : public Base1
{
public:
Derived2(): m_common(this) {}
private:
Common m_common;
}
class Derived2 : public Base2
{
public:
Derived2(): m_common(this) {}
private:
Common m_common;
}
There is a potential risk of going this way though. Since member object(Common) is constructed first before the outer object(Derived1 or Derived2), you want to make sure no methods from the Derivedx object is called in Common's constructor.
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.