As an example, I have two classes A and B. An object of B is a member of class A (container). What is the best way to access data of container class (A) from the member class (object of B).
Also, I don't want to use inheritance (B -> A) as B is not logically derived from A.
Below is the simple representation of my problem.
1 2 3 4 5 6 7 8 9
class B {
int temp;
/* Some function which needs data of A */
}
class A {
int data;
B b;
}
In OO terms, "is-a" implies inheritance whereas "has-a" implies containment. You say you do not want
inheritance, yet you use the "is-a" relationship.
Second, whereas you say "an object of B (is-a) member of A", what you implement is "an object of A
(has-a) member of B", since existence of A implies existence of B and not vice versa.
So I'm not sure if I know what you are really looking for.
It might be something as simple as an accessor function, or perhaps you need to rethink your design.
EDIT: to summarize, your comment on line 3 is unimplementable as is, because not all Bs have an A.
(All As have a B, though).
Let me put my question clearly. Since I am beginner to C++, I will try to describe the problem that I want to solve without using any C++ terminology.
I have a module (X) and it is made up of multiple sub-modules (Y1, Y2, ...) and their combination. Module (X) possesses a common data which is required by all the sub-modules at some point of time. So basically I want to make that common data accessible by sub-modules (Y1, Y2, ...) at run time.
So, what is the best design for solving the above problem in C++ ?
That's a bit unusual. X has a set of attribute groups Y1, Y2, Y3 plus other stuff Z. But then you say that Y1, Y2, and Y3
need to access Z. So it sounds like Y1, Y2, Y3, etc are not self-standing. This sounds like an improper design, if I
understand you correctly. Can you give me a concrete example?
For example, take a computer. If I want to model it then I will define a class for computer which contains objects of monitor class, processor class, hard disk class etc. as members. Each sub-module has its own functionality. But the identification of the computer is common and typically exists with computer class. There could be some situation where processor want to know the identity of the computer it is part of.
My problem is exactly like this. I need a mechanism to share some common data like identification in the above example with the member classes instead of replicating it in all member classes.
class A
{
public:
A() : myB(this) // ctor -- give myB the 'this' pointer
{ }
void CommonFunc(); // B will need to call this function
private:
B myB;
};
class B
{
public:
B(A* container) : myA(container) // ctor, takes the container, records it
{ }
void DoSomething()
{
// call the container function here
myA->CommonFunc();
}
private:
A* myA;
};
This type of scenario should be avoided because it requires B have knowledge of A. I agree with jsmith that this sounds like a design issue. A class shouldn't have to poke its owners. Instead, the owners should pass all necessary info to the class in the form of function parameters.
Ideally you'd want each sub-module to be aware of itself, but not aware of anything greater than it. As soon as the sub-module becomes aware of the main module, then you create all sorts of interdependencies which make the code much harder to maintain and expand.
I have also thought of the same thing. And, I agree with both of you that such design doesn't really look good. I guess I will just replicate the required data with all the sub-modules.
Please let me know if you have any better design approach to solve the aforementioned problem.
Well, there are solutions to the C++ syntax problem. Disch gave code for one and mentioned another (using
references instead of pointers). A third alternative is to factor the common data out of the superclass. For
example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
struct common_data { /* ... */ };
struct hard_disk {
hard_disk( const common_data& cd ) :
common( cd ) {}
private:
const common_data& common;
};
struct computer {
computer( const common_data& cd ) :
common( cd ), hd( common ) {}
private:
common_data common;
hard_disk hd;
};
When you say that
There could be some situation where processor want to know
the identity of the computer it is part of
, I have to doubt the validity of that
statement. Even in a real computer, the processor knows nothing more about its world
than itself. I would think that the computer as a whole might want to know the ID of
the processor in it. But not the other way around.
Even in a real computer, the processor knows nothing more about its world
than itself. I would think that the computer as a whole might want to know the ID of
the processor in it. But not the other way around.
On second thought, I agree with you. I will consider redesigning my model.