Class forward declaration

K

Kevin Grigorenko

Hello,

I have the definitions of classes A and B in a header file. Class A has a
private member of type B. Class B is defined after class A in the header
file. I place a forward declaration of class B above class A but VS.NET
still complains with:

error C2079: 'TextDB::TextDB::database_version' uses undefined class
'TextDB::TextDB_Version'

namespace TextDB
{
class TextDB_Version;

class TextDB
{
private:
TextDB_Version database_version;
};

class TextDB_Version
{
[...]
};

} // namespace TextDB

Is this because this is in a header file? I'm confused.

Thanks a lot,
Kevin Grigorenko
 
C

Cy Edmunds

Kevin Grigorenko said:
Hello,

I have the definitions of classes A and B in a header file. Class A has a
private member of type B. Class B is defined after class A in the header
file. I place a forward declaration of class B above class A but VS.NET
still complains with:

error C2079: 'TextDB::TextDB::database_version' uses undefined class
'TextDB::TextDB_Version'

namespace TextDB
{
class TextDB_Version;

class TextDB
{
private:
TextDB_Version database_version;

How much space should the compiler allocate for this class? It can't know at
this point. It would work to say

TextDB_Version *pdatabase_version;

because all pointers have the same size.
};

class TextDB_Version
{
[...]
};

} // namespace TextDB

Is this because this is in a header file? I'm confused.

Thanks a lot,
Kevin Grigorenko
 
P

Phlip

I have the definitions of classes A and B in a header file. Class A has a
private member of type B. Class B is defined after class A in the header
file. I place a forward declaration of class B above class A but VS.NET
still complains with:

error C2079: 'TextDB::TextDB::database_version' uses undefined class
'TextDB::TextDB_Version'

namespace TextDB
{
class TextDB_Version;

class TextDB
{
private:
TextDB_Version database_version;
};

class TextDB_Version
{
[...]
};

} // namespace TextDB

Is this because this is in a header file? I'm confused.

C++ obeys parsing rules that behave as-if the compiler were only allowed to
"know" things that have been defined "above" where they are used.

(Also, C++'s core language parses after the preprocessor commands, so the
location of a declaration "in a header file" is irrelevant.)

As a rubric, think of the definition of a class (the {} part) as declaring a
classes "size", and think of the definition only working if the compiler
knows the size of each component object.

So, at this line...
class TextDB
{
private:
TextDB_Version database_version;
};

The compiler is trying to determine the size of TextDB. But it does not yet
know the size of TextDB_Version. So it can't define TextDB in terms of
TextDB_Version, which is not defined yet.

The solution is to put TextDB_Version above TextDB. C++'s object
construction rules take precedence - slightly - over any grandiose ideals of
perfectly encapsulated objects.
 
J

Jonathan Mcdougall

I have the definitions of classes A and B in a header file. Class A has a
private member of type B. Class B is defined after class A in the header
file. I place a forward declaration of class B above class A but VS.NET
still complains with:

For the compiler to know the exact size of a class, it must know the
exact size of its members. By putting only a declaration, the
compiler does not know the size of the class, hence the error.
error C2079: 'TextDB::TextDB::database_version' uses undefined class
'TextDB::TextDB_Version'

namespace TextDB
{
class TextDB_Version;

class TextDB
{
private:
TextDB_Version database_version;
};

class TextDB_Version
{
[...]
};

} // namespace TextDB

Is this because this is in a header file? I'm confused.

Take a look :

class A
{
int i;
};

Here the compiler knows 'A' will have the size
sizeof(int) + implementation_defined_things

In your class :

class TextDB
{
private:
TextDB_Version database_version;
};

the compiler tries the same thing :
sizeof(TextDB_Version) + implementation_defined_things

and just cannot find the size of TextDB_Version since you only
declared it.

You have got two choices :

1) Define the class TextDB_Version *before* TextDB

2) Make database_version a pointer and allocate the
memory dynamically


Jonathan
 
K

Kevin Grigorenko

Jonathan Mcdougall said:
I have the definitions of classes A and B in a header file. Class A has a
private member of type B. Class B is defined after class A in the header
file. I place a forward declaration of class B above class A but VS.NET
still complains with:

For the compiler to know the exact size of a class, it must know the
exact size of its members. By putting only a declaration, the
compiler does not know the size of the class, hence the error.
error C2079: 'TextDB::TextDB::database_version' uses undefined class
'TextDB::TextDB_Version'

namespace TextDB
{
class TextDB_Version;

class TextDB
{
private:
TextDB_Version database_version;
};

class TextDB_Version
{
[...]
};

} // namespace TextDB

Is this because this is in a header file? I'm confused.

Take a look :

class A
{
int i;
};

Here the compiler knows 'A' will have the size
sizeof(int) + implementation_defined_things

In your class :

class TextDB
{
private:
TextDB_Version database_version;
};

the compiler tries the same thing :
sizeof(TextDB_Version) + implementation_defined_things

and just cannot find the size of TextDB_Version since you only
declared it.

You have got two choices :

1) Define the class TextDB_Version *before* TextDB

2) Make database_version a pointer and allocate the
memory dynamically


Jonathan

Thanks a lot, that cleared things up clearly.

Kevin Grigorenko
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top