How to solve this problem?

H

Hooyoo

Following are similar codes of my project:
At first I define two classes in two files:
//ClassA.h
#pragma once
#include "ClassB.h"

class ClassA
{
public:
ClassA(void){};
public:
~ClassA(void){};
};

//ClassB.h
#pragma once
#include "ClassA.h"

class ClassA;

class ClassB
{
public:
ClassB(void){};
public:
~ClassB(void){};
void DoSomething(ClassA obj){};
};


Then main function:
//main.cpp
#include "ClassB.h"

int main(void)
{
return 0;
}

When I complie these codes in VS2005, I get 1 error:
Error 1 error C2027: use of undefined type 'ClassA' d:\v-james\test
code\consoledemo\consoledemo\classb.h 12

So, somebody here please say something about this, thanks.
 
?

=?gb2312?B?xNC2+bbgsaHQ0g==?=

ClassA.h should not include the ClassB.h


"Hooyoo дµÀ£º
"
 
H

Hooyoo

I know in these similar codes ClassA.h no need to include classb.h,
but in my real project I need do this.
Can I solve this problem in other ways?
 
M

mimi

"Hooyoo дµÀ£º
"
Following are similar codes of my project:
At first I define two classes in two files:
//ClassA.h
#pragma once
#include "ClassB.h"

class ClassA
{
public:
ClassA(void){};
public:
~ClassA(void){};
};

//ClassB.h
#pragma once
#include "ClassA.h"

Here, you include "ClassA.h" in "ClassB.h", and include "ClassB.h" in
"ClassA.h". I am not quite clear about the link issues.Maybe some one
could explain it more clearly.
But I am sure that there is only one "include" works, and it seems to
be the include "ClassB.h" in "ClassA.h", as you declare "class ClassA"
below.
class ClassA;

Here, you pre-declare the classA.It just tell the compile that ClassA
is a class defined somewhere, so you can declare instances of ClassA in
this file scope.But ClassB doesn't know anything about ClassA.
class ClassB
{
public:
ClassB(void){};
public:
~ClassB(void){};
void DoSomething(ClassA obj){};

When you define the member function Dosometing, you just know ClassA is
a class but nothing more. Access to any member of the classA will be
undefined.When the function takes place, the compile does not know how
to create a temporary object of ClassA, as "it was not defined".
You could use ClassA * here just for compile, but you still can't
access any member of ClassA through the pointer.
 
C

cppcoder

Hooyoo said:
Following are similar codes of my project:
At first I define two classes in two files:
//ClassA.h
#pragma once
#include "ClassB.h"

class ClassA
{
public:
ClassA(void){};
public:
~ClassA(void){};
};

//ClassB.h
#pragma once
#include "ClassA.h"

class ClassA;

class ClassB
{
public:
ClassB(void){};
public:
~ClassB(void){};
void DoSomething(ClassA obj){};
};


Then main function:
//main.cpp
#include "ClassB.h"

int main(void)
{
return 0;
}

When I complie these codes in VS2005, I get 1 error:
Error 1 error C2027: use of undefined type 'ClassA' d:\v-james\test
code\consoledemo\consoledemo\classb.h 12

So, somebody here please say something about this, thanks.

no_dot_h headers like to go with #ifndef-#define-#endif
 
P

Peter Liu

Compiler job do it, because it don't recognise what to compile first
giving some file, by what you say, ".h" files. Also, i think always
writing 'public' to indicate what is publicised is good too. That
increase readable.

Best,
Peter Liu
 
B

Ben Howards

That's not really true, #defien is kewords originally from C not C++.
header files u say are c++ not c. there is no such things as #ifndef
definetion in C++.

-Ben Howards
~FPCP=for potatoes chip pickers~
 
S

Salt_Peter

Hooyoo said:
Following are similar codes of my project:
At first I define two classes in two files:
//ClassA.h
#pragma once
#include "ClassB.h"

class ClassA
{
public:
ClassA(void){};
public:
~ClassA(void){};
};

//ClassB.h
#pragma once
#include "ClassA.h"

class ClassA;

remove the above line. ClassA is already defined in ClassA.h
You should use #ifndef, #define and #endif directives if you want to be
portable (instead of pragma once).
class ClassB
{
public:
ClassB(void){};
public:
~ClassB(void){};
void DoSomething(ClassA obj){};
};


Then main function:
//main.cpp
#include "ClassB.h"

Remember, compilers don't know that header files exist at compilation
time.
To explain the issue, the compiler injects the ClassB.h contents here
in replacement of the #include directive during precompilation. And if
you look closely at that header, it in turn injects ClassA.h before the
declaration and definition of Class B.

So you want to end up with:

ClassA {...};
ClassB {...};
int main() { ... }

If you don't remove the forward declaration of ClassA, you get this:

ClassA {...};
ClassA;
ClassB {...};
int main() { ... }

which explains the error below... the redeclaration hides the previous
definition.
 
G

gustavo.scotti

Hooyoo,

You must move what is common for both files to a third one, and then
include this third one to both of your original files.
 
H

Howard

Please don't top-post. Put your replies at the end, or interspersed with
what you're replying to. (I've re-arragned the converstaion below.)
"Hooyoo P45@#:
"

Why do you need to include that header?

Why are you forward-declaring ClassA and ALSO including its header? Do one
or the other.

Why do you include a file but never use it?

DP6y6`1!PR said:
ClassA.h should not include the ClassB.h
I know in these similar codes ClassA.h no need to include classb.h,
but in my real project I need do this.

Why? Show us code which actually represents the problem you're having. The
above code does not.
Can I solve this problem in other ways?

Yes, I'm sure you can, but we don't know what the problem is.

You might want to look at the FAQ: http://www.parashift.com/c++-faq-lite/

Or do a Google Search for "C++ circular dependency".

-Howard
 
H

Howard

Howard said:
Please don't top-post. Put your replies at the end, or interspersed with
what you're replying to. (I've re-arragned the converstaion below.)

Looks like I re-arranged a few letters there! I think my fingers are
dyslexic. :)

Should be:
"re-arranged the conversation"

-Howard
 
H

Hooyoo

mimi said:
"Hooyoo дµÀ£º
"

Here, you include "ClassA.h" in "ClassB.h", and include "ClassB.h" in
"ClassA.h". I am not quite clear about the link issues.Maybe some one
could explain it more clearly.
But I am sure that there is only one "include" works, and it seems to
be the include "ClassB.h" in "ClassA.h", as you declare "class ClassA"
below.


Here, you pre-declare the classA.It just tell the compile that ClassA
is a class defined somewhere, so you can declare instances of ClassA in
this file scope.But ClassB doesn't know anything about ClassA.


When you define the member function Dosometing, you just know ClassA is
a class but nothing more. Access to any member of the classA will be
undefined.When the function takes place, the compile does not know how
to create a temporary object of ClassA, as "it was not defined".
You could use ClassA * here just for compile, but you still can't
access any member of ClassA through the pointer.

Thanks to all guys. But I think only mimi really understand me, other
guys totally lost, but still thank you.
 
H

Howard

Thanks to all guys. But I think only mimi really understand me, other
guys totally lost, but still thank you.

Well, if we were lost, it's because you didn't post "real" code, and didn't
follow up with answers to our questions. Don't blame us if we can't read
your mind.
 
T

Tristan Penman

If I'm not mistaken, you can solve this problem doing the following.
Note that no extra files are included in ClassA.h and ClassB.h


// File: ClassA.h
class ClassB; // Declaration of ClassA so that ClassB knows it exists
class ClassA
{
// something to do with ClassB
};

------------------------------------------------

// File: ClassB.h
class ClassA; // Declaration of ClassB so that ClassA knows it exists
class ClassB
{
// something to do with ClassA
}

------------------------------------------------

// File: ClassA.cpp
#include "ClassA.h"
#include "ClassB.h"

-------------------------------------------------

// File: ClassB.cpp
#include "ClassA.h"
#include "ClassB.h"

The limitation of this is that you can't access members of ClassA in
ClassB.h, or ClassB in ClassA.h. You can, however, use ClassA.cpp and
ClassB.cpp to do anything you need.

I have not tested this with anything more than a few pointers. (i.e
ClassA * pClassA). I'm not sure if it will let you use non-pointer
members to cross-referenced classes.

-- Tristan.
 
T

tetra

Hi!

I think that the only one who realy touched the real problem was
Howard. Hooyoo, you did created a CYCLYC dependency between files!!!
That's the problem! A solution would be to use pointers and references
into one of the headers and to elimnate the need to include the header
itself. In that case the compilator won't ask you about the class
definition. It suffices the declaration. Thus, try to have, let's say
in header of classA, only pointers and references of type classB (every
method of classA that was previously inline and made calls to classB
goes into .cpp):

//ClassA.h
#pragma once
//declare classB
class classB;

class ClassA
{
public:
ClassA(void) : cB ( 0 ){};
const classB & func1( classB *) ;
void funct2(const classB & );

public:
~ClassA(void){};

private:
classB *cB;
};


Now, everything that is releated to the implementation of B goes into
..cpp:

//ClassA.cpp
#include "ClassA.h"
#include "ClassB.h" // HERE YOU CAN INCLUDE classB

const classB & ClassA::func1( classB *){...}
void ClassA::funct2(const classB & ) {...}


The header of B could remain the same:

//ClassB.h
// #pragma once
#include "ClassA.h"

//!!!!!!!!! it doesn't matter if you declare the class after its
definition
class ClassA;

class ClassB
{
public:
ClassB(void){};
public:
~ClassB(void){};
void DoSomething(ClassA obj){};
};



Then main function:
//main.cpp
#include "ClassB.h"

int main(void)
{
return 0;
}




enjoy,
dreqEu.
 
S

Salt_Peter

tetra said:
Hi!

I think that the only one who realy touched the real problem was
Howard. Hooyoo, you did created a CYCLYC dependency between files!!!
That's the problem! A solution would be to use pointers and references
into one of the headers and to elimnate the need to include the header
itself. In that case the compilator won't ask you about the class
definition. It suffices the declaration. Thus, try to have, let's say
in header of classA, only pointers and references of type classB (every
method of classA that was previously inline and made calls to classB
goes into .cpp):

//ClassA.h
#pragma once
//declare classB
class classB;

classB does not exist
class ClassA
{
public:
ClassA(void) : cB ( 0 ){};

remove semicolon above.
const classB & func1( classB *) ;

classB does not exist.
void funct2(const classB & );

public:
~ClassA(void){};

private:
classB *cB;

classB does not exist.
};


Now, everything that is releated to the implementation of B goes into
.cpp:

//ClassA.cpp
#include "ClassA.h"
#include "ClassB.h" // HERE YOU CAN INCLUDE classB

const classB & ClassA::func1( classB *){...}

same, there is no classB, only ClassB
void ClassA::funct2(const classB & ) {...}


The header of B could remain the same:

//ClassB.h
// #pragma once
#include "ClassA.h"

//!!!!!!!!! it doesn't matter if you declare the class after its
definition
class ClassA;

class ClassB
{
public:
ClassB(void){};

remove the semicolons
public:
~ClassB(void){};
void DoSomething(ClassA obj){};

remove the semicolon above
};



Then main function:
//main.cpp
#include "ClassB.h"

int main(void)
{
return 0;
}

The correct way to forward declare would be as follows, note that
templates would do away with the problems at hand:

// ClassA.h
#ifndef CLASSA_H_
#define CLASSA_H_

#include "ClassB.h"
class ClassB;

class ClassA {
ClassB* p_B;
public:
ClassA( void ) : p_B(0) { }
~ClassA() { }
const ClassB& func1() const;
void funct2(const ClassB &);
};
#endif

//ClassA.cpp
#include "ClassA.h"

const ClassB& ClassA::func1() const
{
return *p_B;
}
void ClassA::funct2(const ClassB& r_b)
{
// ...
}

// ClassB.h
#ifndef CLASSB_H_
#define CLASSB_H_

#include "ClassA.h"
class ClassA;

class ClassB {
public:
ClassB() { }
~ClassB() { }
void DoSomething( const ClassA& r_a ) { }
};
#endif

// test.cpp
#include "ClassB.h"

int main()
{
ClassB instance;
return 0;
}

Although i'ld rather *.hpp headers over *.h headers.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top