0

I need to develop a fast algorithm, and the natural structure of the problem would be

class A {B b; C c;};
class B {};
class C {};

with some methods of class B and C using fields of class A. But I suppose that for scope reasons this is not possible. How can I structure this better? Maybe including a class A pointer inside B and C?

Ajay
  • 16,823
  • 9
  • 50
  • 94
user1403546
  • 1,379
  • 1
  • 16
  • 32
  • 3
    What you have will work fine if you put class A below B and C so the compiler has a definition of B and C when it sees them used in A. – John Zwinck Oct 08 '14 at 12:10
  • `B` and `C` should be defined before `A`, then you can define your method after both definitions. You may have to do some forward declaration. – Jarod42 Oct 08 '14 at 12:11
  • 3
    And if you type `class`, not `Class`, in c++ ... – quantdev Oct 08 '14 at 12:11
  • I would argue that a natural order is like you say. If A depends on B and C it would seem natural that they are declared before A. @Jarod42 I think you also meant declared. They don't have to be defined (at least not until linking time). – luk32 Oct 08 '14 at 12:21
  • @luk32: Since OP uses object and not pointer/reference, the classes has to be defined. (So the methods are at least declared, and can/should be defined later) – Jarod42 Oct 08 '14 at 12:26
  • @Jarod42 Of course, you are right. This got me ["*(In other words, "forward declaration" is something of a misnomer, since there are no other forms of class declarations in C++.)*"](http://stackoverflow.com/a/1410632/1133179). Blushes in shame. – luk32 Oct 08 '14 at 12:33

3 Answers3

3

Not including a pointer to A inside B and C, but including the pointer in the argument list of the methods that need the elements of A (not so good solution, though).

But if instances of B and C are part of the state of an instance of A and also need other parts of the instance of A, then you should think about moving the methods from B and C to A. Reason: if the method operates on b, c and other parts of a, then it is likely, that it is an behaviour of a.

UniversE
  • 2,172
  • 13
  • 19
1

A naive (straightforward) solution is to simply pass a reference to A to constructors for both B and C:

class B
{
public:
  B (const A& a) : mA (a) {}
private:
  const A& mA; 
};

Or maybe better yet, pass references to the fields you actually need:

class B
{ 
public:
  B (const int& foo, const std::string& bar) : mFoo (foo), mBar (bar) {};
private:
  const int& mFoo;
  const std::string mBar;
};

But the fact that the problem at hand leads me to this kludgy straightforward solution is a code smell. I suspect that the entire design is broken.

I wonder what A's real purpose really is? Is it simply to be a holder for a B and a C? Does it have a job? Is it trying to do too much?

Or maybe the problem is in the opposite direction. Maybe in an attempt to squeeze every single thing in to an object-shaped box, you have created a machine that is more complicated than it needs to be. Should B's and C's tasks really be the responsibility of A? Or perhaps even (gasp) free functions?

John Dibling
  • 94,084
  • 27
  • 171
  • 303
  • Some class A methods require values stored in both classes B and C as well as other values not stored there. This is why I thought to store other values in another class (A). Since I have a lot of templates in my code, I'd like to avoid defining functions depending on a large number of templates and thought this was the easiest way... Thank you for your answer – user1403546 Oct 08 '14 at 13:04
  • Perhaps those values should be in another `class` (or `struct`), `D`, which `A`, `B`, and `C` each get a copy of/reference to? – John Dibling Oct 08 '14 at 13:36
0

You may need to use interfaces, i.e abstract base classes for B and C, let's call them IB and IC (interface to B and C).

a.h includes ib.h and ic.h.

The services provided by B and C are only used through the interface base classes.

b.h and c.h includes a.h. (and of course ib.h and ic.h, respectively).

But if only the implementation of B and C needs A, then you can manage without the interface base classes - just include a.h only in b.cpp and c.cpp, thereby avoiding the circular dependence in header files.

Erik Alapää
  • 2,335
  • 10
  • 23