Say I have a Proc
class with the following interface:
class Proc
{
public:
void process();
protected:
virtual void do_process() = 0;
private:
int m_counter;
};
Now, say I have two derived classes that implement Proc
interface.
class DerivedProc1:
public Proc
{
protected:
virtual void do_process();
};
class DerivedProc2:
public Proc
{
protected:
virtual void do_process();
};
Now I generate two derived classes as:
Proc* dp1 = new DerivedProc1();
Proc* dp2 = new DerivedProc2();
I would like both dp1
and dp2
to share the same base class instance.
The reason I need that is because Proc::m_counter
must be the same in both processor, meaning, changing its value in one processor must be "seen" by the other one. Of course, Proc::m_counter
is just an example of a variable I'd like share.
what is the standard approach for that issue?
I'm not looking for a quick fix for the issue. meaning:
Proc::m_counter
static
is not desired. I still need it to be bound to a specific Proc
instance. m_counter
outside of Proc
and pass is as a reference to proc
In C++, a derived class object can be assigned to a base class object, but the other way is not possible.
Inheritance and Friendship in C++If a base class has a friend function, then the function doesn't become a friend of the derived class(es). For example, the following program prints an error because the show() which is a friend of base class A tries to access private data of derived class B.
A derived class can have only one direct base class.
You can derive a class from any number of base classes. Deriving a class from more than one direct base class is called multiple inheritance. The order of derivation is relevant only to determine the order of default initialization by constructors and cleanup by destructors.
As stated it is not possible. The following requirements are mutually contradictory:
DerivedProc1
, not "outside of Proc
".DerivedProc2
.DerivedProc1
and the instance of DerivedProc2
are allocated by separate calls to new
, that is to say they are different most-derived objects.Different most-derived objects cannot share a data member. The reason is that a most-derived object is defined to occupy its own region of memory. Only subobjects of the same most-derived object can share members.
If you're willing to relax the "store outside" restriction then the solution is "obvious": have each object hold a shared_ptr
to something with the count in it. Pass the same count-holding object to the constructors of whatever objects you wish to share a count. The only thing making this question difficult is your restriction on where the count is located in memory.
If you're willing to relax the "separate new
calls" restriction then you could use virtual inheritance and construct both Proc
objects as base-class subobjects of a single most-derived object:
class DerivedProc1 : public virtual Proc { ... };
class DerivedProc2 : public virtual Proc { ... };
class CombinedProc : public DerivedProc1, DerivedProc2 { ... };
CombinedProc *dp0 = new CombinedProc();
DerivedProc1 *dp1 = dp0;
DerivedProc2 *dp2 = dp0;
Since none of the classes has a virtual destructor, you must use dp0
(and not dp1
or dp2
) to delete the object. If you give Proc
a virtual destructor then you could use any one (and only one) of them.
I would not advise using virtual inheritance unless you properly understand it. So, since you're going to have to relax one of the requirements I'd normally say that the standard approach is relaxing the first: store the count in a separate object outside of the two objects.
Don't use inheritance. Instead, give DerivedProc1
and DerivedProc1
a member pointer to a Proc
instance and construct both objects with a pointer to a single Proc
object.
Something like this:
class DerivedProc1
{
protected:
Proc *proc;
void do_process(){
proc->process();
}
public:
DerivedProc1(Proc *proc):proc(proc){}
};
Probably best to use std::shared_ptr<Proc>
over raw pointers as derived class members.
Instead of having a base class with a shared resource, have a base class just for the interface, and then a separate object that is shared between the classes, which contains the counter.
First, do_process
must be virtual
and the DerivedProcX
needs to derive from Proc
.
To share the counter you can declare it as static
and make the base class a template, something like this:
class BaseProc {};
template <int n> class Proc : BaseProc
{
virtual void do_process() = 0;
static int m_counter;
}
template <int n> class DerivedProc1 : public Proc<n>
{
void do_process() {}
}
template <int n> class DerivedProc2 : public Proc<n>
{
void do_process() {}
}
int main()
{
// dp1 and dp2 share the same counter
Proc<1>* dp1 = new DerivedProc1<1>;
Proc<1>* dp2 = new DerivedProc2<1>;
// dp3 and dp4 share the same counter, but not the same as dp1 and dp2
BaseProc* dp3 = new DerivedProc1<2>;
BaseProc* dp4 = new DerivedProc2<2>;
}
Of course this solution assumes that you know at compile time what instances will need to share the same counter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With