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.
"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.
> 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.
no_dot_h headers like to go with #ifndef-#define-#endif
Best,
Peter Liu
-Ben Howards
~FPCP=for potatoes chip pickers~
Please don't -- see FAQ item 5.4.
Besides, what you wrote is incorrect.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
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.
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@#:
> "
> > Following are similar codes of my project:
> > At first I define two classes in two files:
> > //ClassA.h
> > #pragma once
> > #include "ClassB.h"
> >
Why do you need to include that header?
> > class ClassA
> > {
> > public:
> > ClassA(void){};
> > public:
> > ~ClassA(void){};
> > };
> >
> > //ClassB.h
> > #pragma once
> > #include "ClassA.h"
> >
> > class ClassA;
Why are you forward-declaring ClassA and ALSO including its header? Do one
or the other.
> >
> > 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;
> > }
Why do you include a file but never use it?
> >
> > 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.
DP6y6`1!PR wrote:
> 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
Looks like I re-arranged a few letters there! I think my fingers are
dyslexic. :-)
Should be:
"re-arranged the conversation"
-Howard
Thanks to all guys. But I think only mimi really understand me, other
guys totally lost, but still thank you.
> 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.
// 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.
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.
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.