C++ 未定义错误

return_zero 2011-09-12 04:41:49
顺便祝各位节日快乐!

我的问题如下:编译如下代码,出现错误:error C2027: use of undefined type 'A'
当我把B.h中的头文件注释掉,把funB2的实现放在B.h中,错误就不报了,但是不知道原因是什么?请各位帮忙解释下。


A.h

// A.h

#ifndef _A_H_
#define _A_H_

class A
{
public:
static A& getTheApp();
void funA();

private:
static A* theApp;

};

#endif

A.cpp

// A.cpp

#include "stdafx.h"
#include "A.h"

A* A::theApp = NULL;

A& A::getTheApp()
{
if (theApp == NULL) {
theApp = new A();
}

return *theApp;
}

void A::funA()
{
printf("funA...\n");
}



B.h

// B.h
#ifndef _B_H_
#define _B_H_

class A;

class B
{
public:
void funB()
{
printf("B...\n");
A::getTheApp().funA();
}
void funB2();

};

#endif

B.cpp

// B.cpp

#include "stdafx.h"
#include "B.h"

void B::funB2()
{
printf("funB2...\n");
}



主程序

#include "stdafx.h"
#include "A.h"
#include "B.h"

int main(int argc, _TCHAR* argv[])
{
A a;
a.funA();
A::getTheApp().funA();

B b;
b.funB();

return 0;
}













...全文
450 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
兆帅 2011-09-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 qq120848369 的回复:]

C/C++ code
// B.h
#ifndef _B_H_
#define _B_H_

#include "A.h"

//class A;

class B
{
public:
void funB()
{
printf("B...\n");
A::getTheApp().funA();
}
void funB2();

}……
[/Quote]
正解~~
return_zero 2011-09-13
  • 打赏
  • 举报
回复
迎候蜡笔小新同学
return_zero 2011-09-13
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 qq120848369 的回复:]

引用 20 楼 return_zero 的回复:

引用 18 楼 luciferisnotsatan 的回复:

把void funB()的实现放到b.cpp里去。

我不太清楚,像这种无限递归include的情况,编译器是如何处理的?即
A.h 包含 B.h
B.h 又包含 A.h
A.h 又包含 B.h
……
子子孙孙无穷匮也!


#ifndef 是做什么用的……
[/Quote]
谢谢,头文件卫士是为了防止一个头文件被多次编译,我的意思是编译器是如何展开的呢?
我的理解是,编译器遇到#include就会替换,像您说的“头文件属于宏操作”,那么这种递归式的展开如何截至呢。
qq120848369 2011-09-13
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 return_zero 的回复:]

引用 18 楼 luciferisnotsatan 的回复:

把void funB()的实现放到b.cpp里去。

我不太清楚,像这种无限递归include的情况,编译器是如何处理的?即
A.h 包含 B.h
B.h 又包含 A.h
A.h 又包含 B.h
……
子子孙孙无穷匮也!
[/Quote]

#ifndef 是做什么用的?
return_zero 2011-09-13
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 luciferisnotsatan 的回复:]

把void funB()的实现放到b.cpp里去。
[/Quote]
我不太清楚,像这种无限递归include的情况,编译器是如何处理的?即
A.h 包含 B.h
B.h 又包含 A.h
A.h 又包含 B.h
……
子子孙孙无穷匮也!
luciferisnotsatan 2011-09-13
  • 打赏
  • 举报
回复
或者,A.h如下写也行

#ifndef _A_H_
#define _A_H_



class A
{
public:
static A& getTheApp();
void A::funA() {
printf("funA...\n");
}

private:
static A* theApp;

};

#include "B.h"
#endif


编译器编译A.cpp时,先include了B.h,然后B的函数里用了A,但此时A还没用编到(可以把include看成文本替换,把B.h的内容替换#include "B.h")。这样,代码就成了

class B{
void fun()
{
...
}
}

class A{
...
}
编译class B时,A还没编译。
luciferisnotsatan 2011-09-13
  • 打赏
  • 举报
回复
把void funB()的实现放到b.cpp里去。
return_zero 2011-09-13
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 qq120848369 的回复:]

楼主多思考下。。你问的已经没有什么意思了。
[/Quote]
以前很少注意这个问题,谢谢你的指点!
mtj530 2011-09-13
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 smiletocandy 的回复:]
学习下, 等大牛。
[/Quote]
+1
qq120848369 2011-09-13
  • 打赏
  • 举报
回复
楼主多思考下。。你问的已经没有什么意思了。
SmileToCandy 2011-09-13
  • 打赏
  • 举报
回复
学习下, 等大牛。
return_zero 2011-09-13
  • 打赏
  • 举报
回复
我原先的理解:预处理器用指定的头文件的内容替代每个#include,如果一个头文件#include自己,那么预处理器是怎么处理的呢。
好吧就这样吧
return_zero 2011-09-13
  • 打赏
  • 举报
回复
谢谢,我的疑惑:
#ifndef 作用是检测指定的预处理器变量 XXX_H 是否未定义,如果未定义后面的内容才被处理。
如果定义了,只是后面的代码不被处理,但是并没有说这段代码不被展开。

我的理解是,编译器遇到#include就会替换,像您说的“头文件属于宏操作”,那么这种递归式的展开如何截至呢

[Quote=引用 25 楼 qq120848369 的回复:]

引用 22 楼 return_zero 的回复:

引用 21 楼 qq120848369 的回复:

引用 20 楼 return_zero 的回复:

引用 18 楼 luciferisnotsatan 的回复:

把void funB()的实现放到b.cpp里去。

我不太清楚,像这种无限递归include的情况,编译器是如何处理的?即
A.h 包含 B.h
B.h……
[/Quote]
qq120848369 2011-09-13
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 return_zero 的回复:]

引用 21 楼 qq120848369 的回复:

引用 20 楼 return_zero 的回复:

引用 18 楼 luciferisnotsatan 的回复:

把void funB()的实现放到b.cpp里去。

我不太清楚,像这种无限递归include的情况,编译器是如何处理的?即
A.h 包含 B.h
B.h 又包含 A.h
A.h 又包含 B.h
……
子……
[/Quote]

#ifndef XXX_H
#define XXX_H
...
#endif

看到#define XXX_H没。。

第一次#INCLUDE就会调用到#define XXX_H

第二次#include#ifndef XXX_H为假!!!!!!!!!!
return_zero 2011-09-12
  • 打赏
  • 举报
回复
顶一下
return_zero 2011-09-12
  • 打赏
  • 举报
回复
如果将 B.h 中的 #include "A.h" 去掉,就正确了,但是为什么?
return_zero 2011-09-12
  • 打赏
  • 举报
回复
谢谢你,还是有点儿疑问,13L 的情况

// A.h
#ifndef _A_H_
#define _A_H_

#include "B.h"

class A
{
public:
static A& getTheApp();
void A::funA() {
printf("funA...\n");
}

private:
static A* theApp;

};
#endif

// A.cpp

#include "stdafx.h"
#include "A.h"

A* A::theApp = NULL;

A& A::getTheApp()
{
if (theApp == NULL) {
theApp = new A();
}

return *theApp;
}


// B.h
#ifndef _B_H_
#define _B_H_

#include "A.h"

class B
{
public:
void funB()
{
printf("funB...\n");
A::getTheApp().funA();
}

};
#endif

// B.cpp

#include "stdafx.h"
#include "B.h"


#include "stdafx.h"
#include "A.h"
#include "B.h"

int main(int argc, _TCHAR* argv[])
{
A a;
a.funA();
A::getTheApp().funA();

B b;
b.funB();

return 0;
}

qq120848369 2011-09-12
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 return_zero 的回复:]
引用 12 楼 qq120848369 的回复:

重要知识点:

1,源文件独立遍历
2,头文件属于宏操作,不会单独参与编译
3,依赖声明还是依赖定义,一定要分清楚
4,头文件里定义函数体属于内联函数,慎重。

谢谢!
再问下这个情况是什么原因呢?

C/C++ code

// B.h
#include "A.h"
// ...
A::getTheApp()……
[/Quote]

自己理顺一下吧,我觉得没有什么问题了。
return_zero 2011-09-12
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 qq120848369 的回复:]

重要知识点:

1,源文件独立遍历
2,头文件属于宏操作,不会单独参与编译
3,依赖声明还是依赖定义,一定要分清楚
4,头文件里定义函数体属于内联函数,慎重。
[/Quote]
谢谢!
再问下这个情况是什么原因呢?

// B.h
#include "A.h"
// ...
A::getTheApp().funA();// 包含了,还是提示:has not been declared
qq120848369 2011-09-12
  • 打赏
  • 举报
回复
重要知识点:

1,源文件独立遍历
2,头文件属于宏操作,不会单独参与编译
3,依赖声明还是依赖定义,一定要分清楚
4,头文件里定义函数体属于内联函数,慎重。
加载更多回复(11)

64,660

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧