Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declare but not define inner struct/class - legal C++ or not?

Is following code legal C++ or not?

class Foo
{
  class Bar;

  void HaveADrink(Bar &bar);
  void PayForDrinks(Bar &bar);

  public:
  void VisitABar(int drinks);
};

class Foo::Bar
{
  public:
  int countDrinks;
};

void Foo::HaveADrink(Bar &bar)
{
  bar.countDrinks++;
}
void Foo::PayForDrinks(Bar &bar)
{
  bar.countDrinks = 0;
}
void Foo::VisitABar(int drinks)
{
  Bar bar;
  for (int i=0; i<drinks; i++) HaveADrink(bar);
  PayForDrinks(bar);
}

Both Visual C++ and GCC accepts it, however the code seems somewhat strange to me and I would hate to have it refused by some future compiler.

Still, the pattern seems useful to me to reduce compile time dependencies - I often use it to declare structs which are used to pass some "context" (a bunch of variables) which are shared between a few functions which all reside in the same cpp file, and this way I do not have to introduce the "context" definition into the public interface.

like image 351
Suma Avatar asked Oct 14 '09 07:10

Suma


2 Answers

legal, and indeed usefull to hide implementation details to the outside world.

like image 160
stijn Avatar answered Nov 12 '22 12:11

stijn


[edit] I originally said this was the "pimpl idiom" : http://c2.com/cgi/wiki?PimplIdiom but I agree that this is just part of pimpl is about. This technique is used by pimpl.

You're "forwarding" class Bar inside of class Foo. Perfectly legal as long as you don't do anything inside the definigino of Foo that would require the sizeof Bar. You can reference Bar using pointer or reference (Bar* or Bar&), but if you declare a data member in Foo such as this:

private: Bar _bar;

It wouldn't work. The reason is because the definition of Foo must be enough to determine the sizeof Foo. Since the size of Bar is unknown inside the definition of Foo, it would make the size of Foo indeterminate. But using a pointer would work:

private: Bar* _bar;

Because the sizeof of pointer is the same, and thus known, regardless of how Bar will be later defined.

like image 42
zumalifeguard Avatar answered Nov 12 '22 11:11

zumalifeguard