Reputation: 1279
I have class A,B,C,D which all have a member of class X in it. I have another class called class P.
In my class A I create an instance of class P as well. In class P I need to access the X instance of A and a method of A (this method is available in class B,C,D as well with the same method signature and parameters), therefore I pass class A to class P while initializing class P.
so The code looks like;
class P;
class A{
public:
X x;
P *p;
A(){
x = new X();
};
void setData(){
p = new P(this);
}
};
class P{
public:
A *a;
P(A *_A){
a = _A;
a->x.resetVal();
}
};
Now I need to create instances of P in class B,C,D as well and pass instances of those classes to P.
To my knowledge to achieve this I must either make A,B,C,D a child class of a new class (class Parent) and set the constructor of class P to accept class Parent instance, or I must create separate constructors for classes A,B,C,D in class P.
class Parent {
X x;
}
class P;
class A:: Parent{
...........//code
};
class P{
public:
Parent *prnt;
Impl(Parent *prnt){
.........//code
}
};
---------------------- OR -------------------------
class P{
public:
A *a;
B *a;
C *a;
D *a;
Impl(A *_A){
.............//code
}
Impl(B *_B){
.............//code
}
Impl(C *_C){
.............//code
}
.............//code
};
I do not want to change class A,B,C,D because that would be complicated as those classes were not written by me. Is there another way to achieve this other than the two above methods?
Any help would be appreciated. Thanks.
Upvotes: 2
Views: 1946
Reputation: 5118
There is a lot of information about the relationships between your classes and what you can or cannot change in which classes that's missing in order for me to completely understand what you need. However, it looks to me as if making P a template class could be a solution:
template<typename T>
class P {
public:
T *t_;
P(T* t){
t_ = t;
t->x.resetVal();
}
};
If the access to the X instance is not the same across classes A, B, C, D, well you can make that a template parameter too:
class X {
public:
void doStuff() {};
};
class A {
public:
X x_;
};
class B {
public:
X y_;
};
template<typename T, X (T::*XAccessor)>
class P {
public:
T* t_;
P (T* t)
: t_{t} {
}
void doStuffWithX() {
(t_ ->* XAccessor).doStuff();
}
};
void testDoingStuffWithX() {
A a;
B b;
P<A, &A::x_> pa(&a);
P<B, &B::y_> pb(&b);
pa.doStuffWithX();
pb.doStuffWithX();
}
If you also need to manipulate the different P template instances uniformly, you can use P as a common base class of your templated class:
class P {
virtual ~P() {}
virtual void doSomething() = 0;
};
template<typename T>
class SpecificP : public P {
public:
T *t_;
SpecificP(T* t){
t_ = t;
t->x.resetVal();
}
override void doSomething() {
...
}
};
Upvotes: 1
Reputation: 423
If you only need to access the X instance in each of the classes, you can pass the pointer to the X instance to the constructor of P.
class P {
public:
X* x;
P(X* _x) {
x = _x;
// code
}
};
class A{
public:
X x;
P *p;
A(){
x = new X();
};
void setData(){
p = new P(x);
}
};
Upvotes: 1