tags:

views:

1047

answers:

6

If I create a class like so:

// B.h
#ifndef _B_H_
#define _B_H_

class B
{
private:
    int x;
    int y;
};

#endif // _B_H_

and use it like this:

// main.cpp
#include <iostream>
#include <vector>

class B; // Forward declaration.

class A
{
public:
    A() {
        std::cout << v.size() << std::endl;
    }

private:
    std::vector<B> v;
};

int main()
{
    A a;
}

The compiler fails when compiling main.cpp. Now the solution I know is to #include "B.h", but I'm curious as to why it fails. Neither g++ or cl's error messages were very enlightening in this matter.

+3  A: 

To instantiate A::v, the compiler needs to know the concrete type of B.

If you're trying to minimize the amount of #included baggage to improve compile times, there are two things you can do, which are really variations of each other:

  1. Use a pointer to B
  2. Use a lightweight proxy to B
Josh
+17  A: 

The compiler needs to know how big "B" is before it can generate the appropriate layout information. If instead, you said std::vector<B*>, then the compiler wouldn't need to know how big B is because it knows how big a pointer is.

Curt Hagenlocher
A: 

The reason you can't use a forward declaration is because the size of B is unknown.

There's no reason in your example that you can't include B.h inside of A.h, so what problem are you really trying to solve?

Edit: There's another way to solve this problem, too: stop using C/C++! It's so 1970s... ;)

Brad Wilson
'stop using C/C++' doesn't appear to be a solution to the original problem. patient: "doctor, it hurts when i do this", doctor: "well, then don't do that!" Is there another language or tool that can interoperate well with C++ that you would suggest instead?
Aaron
A: 

Thanks guys. I figured it was something like that.

@Brad:
Like I said in the question text, I know the solution, I'm just thirsting for knowledge. :')

@Brad'sEdit:
Very true. Alas, I am not using C++ by choice. :(

Bernard
+1  A: 

It's more than just the size of B that's needed. Modern compilers will have fancy tricks to speed up vector copies using memcpy where possible, for instance. This is commonly achieved by partially specializing on the POD-ness of the element type. You can't tell if B is a POD from a forward declaration.

MSalters
+1  A: 

This doesn't matter whether you use a vector or just try to instantiate one B. Instantiation requires the full definition of an object.

Greg Rogers