昨天发的一个帖子: http://topic.csdn.net/u/20110912/16/6b625bc9-0b85-421e-bde2-01bc5f7cbf76.html
(暂时还存在问题,仍未结贴)
下面叙述详细的问题:
遇到这样一个情况,下面是一个简化的说明:
在A.h中定义了一个类模版,并且在A.h中需要#include "B.h"(即,需要知道B的定义)
而在B.h中又使用了A.h中定义的模版,因此也需要#include "A.h"(即,又需要知道A的定义)
问题1:这段代码应该是不对的,但在gcc3.3.4上没有报错,而在gcc4.1.2上报错:
error: incomplete type 'CXXX' used in nested name specifier
问题2:通常相互依赖的2个类,把有依赖项的函数的具体实现都放入CPP中,类似的问题就解决了。但是A.h中使用的是类模版,大部分编译器只支持 inclusion compliation model,即,不支持分别编译模型。所以,将依赖的代码放在CPP中就不可行了。
有些理解不对的地方,请大大们指教!分数不多,见谅
38 个解决方案
#1
头文件相互包含,不但要用到#include,而且还要分别声明要用到的类。
比如A.h中,添加#include"B.h",而且要添加class B;B.h中也是一样,否则就报错。
编译器不支持模板分离编译,这也是没有办法的事情,要用类模板,就把实现也写在头文件中吧。
比如A.h中,添加#include"B.h",而且要添加class B;B.h中也是一样,否则就报错。
编译器不支持模板分离编译,这也是没有办法的事情,要用类模板,就把实现也写在头文件中吧。
#2
1.相互引用不能用对象,只能用引用和指针
2.大部分编译器不支持分离编译
2.大部分编译器不支持分离编译
#3
++
补充一下,解决起来,可以利用CPP文件,就是.h里面只有声明(互相引用的就只用指针引用形式,这样就不需要include了,只要前置声明一下。在cpp里面再include即可)
模板永远不会支持export关键字了。
#4
呵呵 来看看这位老大的解释
#5
A.h中的类模版在B.h中怎么声明呢?
// A.h中的类模版定义
template <class CR,class CS>
class CA : public CBase
{
//...
}
#6
“解决起来,可以利用CPP文件,就是.h里面只有声明”
这个方法我知道,但是在A.h中必须要知道B.h的定义,只有前向声明是不行的。
比如,在A.h中,调用
B::static_funB();// 在A.h中调用B.h中的静态函数,此时在A.h中必须要知道B类型的完整定义
#7
经典的pimpl手法我知道,但是对我的问题又不太一样。
#8
模板的话不支持分开编译,
要把头文件源文件一起包含,如:
#include "test.h"
#include "test.cpp"
要把头文件源文件一起包含,如:
#include "test.h"
#include "test.cpp"
#9
把void funB()的实现放到b.cpp里去。
#10
或者说,您提出的解决方法,如何解决问题2呢?即,头文件A.h中定义的是类模版。
#11
我试过,问题是别的类在使用模版类的时候怎么办,如果#include "B.cpp",可能会出现重复inclusion问题(重复定义问题)。
#12
A.h里没用到B.h的内容。
把#include "B.h"的代码放到A.h最后(#endif上面)。
#13
如果是模版,就把A.cpp里的实现全写到A.h里。把A.cpp删了。
#14
我习惯把他们都放在同一个文件上,前置声明一下就行了
#15
@luciferisnotsatan 12L 谢谢
您说的“A.h里没用到B.h的内容”,鄙人不太理解。
在A.h中必须要知道B.h的定义,只有前向声明是不行的。
比如,在A.h中,调用
B::static_funB();// 在A.h中调用B.h中的静态函数,此时在A.h中必须要知道B类型的完整定义。
您说的“A.h里没用到B.h的内容”,鄙人不太理解。
在A.h中必须要知道B.h的定义,只有前向声明是不行的。
比如,在A.h中,调用
B::static_funB();// 在A.h中调用B.h中的静态函数,此时在A.h中必须要知道B类型的完整定义。
#16
目前就是这样的,模版类是在A.h中定义和实现的,A.cpp中实现了一些其他的函数(说明一下,A.h中除了定义了一个模版类之外,还定义了几个普通的类)。
如果将A.cpp删除,本质上还是没有解决头文件 circular inclusion 的问题,即两个相互依赖的类相互包含的问题。
鄙人写了一个测试的例子:非模版的两个相互包含的类,可以通过把依赖的实现代码移到CPP中得以解决,但是,对于含有模版的两个相互包含的类,就无可奈何了。
下面的代码是——不含模版类时的解决方法:
// A.h
#ifndef _A_H_
#define _A_H_
#include "B.h"
class A
{
public:
static A& getTheApp();
void funA();
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;
}
void A::funA() {
printf("funA...\n");
B b;
printf("i_b = %d\n", b.i_b);
}
////////////////////////////////////////////////
// B.h
#ifndef _B_H_
#define _B_H_
#include "A.h"
class B
{
public:
B(){i_b = 100;}
void funB();
int i_b;
};
#endif
/////////////////////////////////////
// B.cpp
#include "stdafx.h"
#include "B.h"
void B::funB()
{
printf("funB...\n");
A::getTheApp().funA();
}
//////////////////////////////
// 主程序
#include "stdafx.h"
#include "A.h"
#include "B.h"
int main(int argc, _TCHAR* argv[])
{
B b;
b.funB();
return 0;
}
#17
#ifndef _A_H_
#define _A_H_
class A
{
public:
static A& getTheApp();
void funA();
private:
static A* theApp;
};
#include "B.h"
#endif
这样,你就可以把funB放到B.h里去了。
但如果这是都是自己写的代码,建议还是自己整理下思路。看看能不能简化,别做出这么复杂的东西。
#define _A_H_
class A
{
public:
static A& getTheApp();
void funA();
private:
static A* theApp;
};
#include "B.h"
#endif
这样,你就可以把funB放到B.h里去了。
但如果这是都是自己写的代码,建议还是自己整理下思路。看看能不能简化,别做出这么复杂的东西。
#18
++
#19
ifndef
define
endif
define
endif
#20
模板不支持分离编译,所以模板没有CPP文件一说。
#21
谢谢,可能是我没有说清楚,我是在维护编译的代码,现在出现了这样的问题(见顶端问题1)。
我现在把问题再描述一下:
相互依赖的问题就出现了。
我现在把问题再描述一下:
// A.h
#include "B.h"// 要知道B的定义
template <...>// A.h 中的模版类 CA
class CA
{
public:
void funA()
{
B:funB();// 这里需要知道 B 的完整定义
}
};
// B.h
#include "A.h"// 要包含模版类的定义
class B
{
typedef CA<...> CAlias;// 这里需要使用模版类 CA
CAlias * m_b;
//...
static funB();
};
相互依赖的问题就出现了。
#22
A.h中定义的模版类和实现,A.cpp中是另外一些类的实现,见16L
#23
你昨天可没说那是个模板类。
#24
感谢 蜡笔小新 qq120848369的关注!
不知道当初设计者的意图是什么,类之间耦合的比较厉害,而且奇怪为什么gcc 3.3.4没有报错。
PS:第一个帖子还有一个问题没有回答。
#25
学习下,拿分
#26
这个好难懂呀
#27
支持帖子 别沉默了哦
#28
谢谢!
现在通过一种方法编译通过了,正在测试程序是否正确。同时仍然希望有经验的朋友给些建议。
#29
模板支持三种类型
1.全部放进头文件.h里称为置入型模型 可以泛化任何类型
2.声明放在头文件 定义放在cpp中 又称显示实例化 编译时会去编译cpp 要使它能找到编译的类型 必须手动告知编译器要泛化的类型 即 template class TemplateClass<T>;
3.export 声明手动导出 称为分离编译模型 但是目前编译器还不支持 至少vs
如果LZ只是要用模板这个类型可以用前置声明 但是只限用类型 其他情况必须包含头文件
1.全部放进头文件.h里称为置入型模型 可以泛化任何类型
2.声明放在头文件 定义放在cpp中 又称显示实例化 编译时会去编译cpp 要使它能找到编译的类型 必须手动告知编译器要泛化的类型 即 template class TemplateClass<T>;
3.export 声明手动导出 称为分离编译模型 但是目前编译器还不支持 至少vs
如果LZ只是要用模板这个类型可以用前置声明 但是只限用类型 其他情况必须包含头文件
#30
路过求分+学习
#31
"如果LZ只是要用模板这个类型可以用前置声明 但是只限用类型 其他情况必须包含头文件"
格式如何写?此方式好像试过会提示识别不了<符号
好像在搜过的相关文章上看到,在别的文件中使用类模版,必须包含这个模版的定义,我去试下
#32
#ifndef
#endif
#endif
#33
Vc6.0下。。亲试。。可编译通过。。。
#34
在一个头文件中用class声明一下另一个头文件中的类,在另一个头文件中include。一般不建议两个类这般联系,应该好好设计下类层次结构。
#35
学习了。。。
#36
#ifndef AAAAA
#define AAAAA
#include "B.h"
class A{...};
#endif
#define AAAAA
#include "B.h"
class A{...};
#endif
#37
前置声明 class T;只是告知编译器 存在这个类型 主要是用于模板 显示实例化
template class TemplateClass<T>;
只要将这句加到T的.h中就行了 但是这样就只能实例化T 不能实例化其他类型
template class TemplateClass<T>;
只要将这句加到T的.h中就行了 但是这样就只能实例化T 不能实例化其他类型
#1
头文件相互包含,不但要用到#include,而且还要分别声明要用到的类。
比如A.h中,添加#include"B.h",而且要添加class B;B.h中也是一样,否则就报错。
编译器不支持模板分离编译,这也是没有办法的事情,要用类模板,就把实现也写在头文件中吧。
比如A.h中,添加#include"B.h",而且要添加class B;B.h中也是一样,否则就报错。
编译器不支持模板分离编译,这也是没有办法的事情,要用类模板,就把实现也写在头文件中吧。
#2
1.相互引用不能用对象,只能用引用和指针
2.大部分编译器不支持分离编译
2.大部分编译器不支持分离编译
#3
++
补充一下,解决起来,可以利用CPP文件,就是.h里面只有声明(互相引用的就只用指针引用形式,这样就不需要include了,只要前置声明一下。在cpp里面再include即可)
模板永远不会支持export关键字了。
#4
呵呵 来看看这位老大的解释
#5
A.h中的类模版在B.h中怎么声明呢?
// A.h中的类模版定义
template <class CR,class CS>
class CA : public CBase
{
//...
}
#6
“解决起来,可以利用CPP文件,就是.h里面只有声明”
这个方法我知道,但是在A.h中必须要知道B.h的定义,只有前向声明是不行的。
比如,在A.h中,调用
B::static_funB();// 在A.h中调用B.h中的静态函数,此时在A.h中必须要知道B类型的完整定义
#7
经典的pimpl手法我知道,但是对我的问题又不太一样。
#8
模板的话不支持分开编译,
要把头文件源文件一起包含,如:
#include "test.h"
#include "test.cpp"
要把头文件源文件一起包含,如:
#include "test.h"
#include "test.cpp"
#9
把void funB()的实现放到b.cpp里去。
#10
或者说,您提出的解决方法,如何解决问题2呢?即,头文件A.h中定义的是类模版。
#11
我试过,问题是别的类在使用模版类的时候怎么办,如果#include "B.cpp",可能会出现重复inclusion问题(重复定义问题)。
#12
A.h里没用到B.h的内容。
把#include "B.h"的代码放到A.h最后(#endif上面)。
#13
如果是模版,就把A.cpp里的实现全写到A.h里。把A.cpp删了。
#14
我习惯把他们都放在同一个文件上,前置声明一下就行了
#15
@luciferisnotsatan 12L 谢谢
您说的“A.h里没用到B.h的内容”,鄙人不太理解。
在A.h中必须要知道B.h的定义,只有前向声明是不行的。
比如,在A.h中,调用
B::static_funB();// 在A.h中调用B.h中的静态函数,此时在A.h中必须要知道B类型的完整定义。
您说的“A.h里没用到B.h的内容”,鄙人不太理解。
在A.h中必须要知道B.h的定义,只有前向声明是不行的。
比如,在A.h中,调用
B::static_funB();// 在A.h中调用B.h中的静态函数,此时在A.h中必须要知道B类型的完整定义。
#16
目前就是这样的,模版类是在A.h中定义和实现的,A.cpp中实现了一些其他的函数(说明一下,A.h中除了定义了一个模版类之外,还定义了几个普通的类)。
如果将A.cpp删除,本质上还是没有解决头文件 circular inclusion 的问题,即两个相互依赖的类相互包含的问题。
鄙人写了一个测试的例子:非模版的两个相互包含的类,可以通过把依赖的实现代码移到CPP中得以解决,但是,对于含有模版的两个相互包含的类,就无可奈何了。
下面的代码是——不含模版类时的解决方法:
// A.h
#ifndef _A_H_
#define _A_H_
#include "B.h"
class A
{
public:
static A& getTheApp();
void funA();
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;
}
void A::funA() {
printf("funA...\n");
B b;
printf("i_b = %d\n", b.i_b);
}
////////////////////////////////////////////////
// B.h
#ifndef _B_H_
#define _B_H_
#include "A.h"
class B
{
public:
B(){i_b = 100;}
void funB();
int i_b;
};
#endif
/////////////////////////////////////
// B.cpp
#include "stdafx.h"
#include "B.h"
void B::funB()
{
printf("funB...\n");
A::getTheApp().funA();
}
//////////////////////////////
// 主程序
#include "stdafx.h"
#include "A.h"
#include "B.h"
int main(int argc, _TCHAR* argv[])
{
B b;
b.funB();
return 0;
}
#17
#ifndef _A_H_
#define _A_H_
class A
{
public:
static A& getTheApp();
void funA();
private:
static A* theApp;
};
#include "B.h"
#endif
这样,你就可以把funB放到B.h里去了。
但如果这是都是自己写的代码,建议还是自己整理下思路。看看能不能简化,别做出这么复杂的东西。
#define _A_H_
class A
{
public:
static A& getTheApp();
void funA();
private:
static A* theApp;
};
#include "B.h"
#endif
这样,你就可以把funB放到B.h里去了。
但如果这是都是自己写的代码,建议还是自己整理下思路。看看能不能简化,别做出这么复杂的东西。
#18
++
#19
ifndef
define
endif
define
endif
#20
模板不支持分离编译,所以模板没有CPP文件一说。
#21
谢谢,可能是我没有说清楚,我是在维护编译的代码,现在出现了这样的问题(见顶端问题1)。
我现在把问题再描述一下:
相互依赖的问题就出现了。
我现在把问题再描述一下:
// A.h
#include "B.h"// 要知道B的定义
template <...>// A.h 中的模版类 CA
class CA
{
public:
void funA()
{
B:funB();// 这里需要知道 B 的完整定义
}
};
// B.h
#include "A.h"// 要包含模版类的定义
class B
{
typedef CA<...> CAlias;// 这里需要使用模版类 CA
CAlias * m_b;
//...
static funB();
};
相互依赖的问题就出现了。
#22
A.h中定义的模版类和实现,A.cpp中是另外一些类的实现,见16L
#23
你昨天可没说那是个模板类。
#24
感谢 蜡笔小新 qq120848369的关注!
不知道当初设计者的意图是什么,类之间耦合的比较厉害,而且奇怪为什么gcc 3.3.4没有报错。
PS:第一个帖子还有一个问题没有回答。
#25
学习下,拿分
#26
这个好难懂呀
#27
支持帖子 别沉默了哦
#28
谢谢!
现在通过一种方法编译通过了,正在测试程序是否正确。同时仍然希望有经验的朋友给些建议。
#29
模板支持三种类型
1.全部放进头文件.h里称为置入型模型 可以泛化任何类型
2.声明放在头文件 定义放在cpp中 又称显示实例化 编译时会去编译cpp 要使它能找到编译的类型 必须手动告知编译器要泛化的类型 即 template class TemplateClass<T>;
3.export 声明手动导出 称为分离编译模型 但是目前编译器还不支持 至少vs
如果LZ只是要用模板这个类型可以用前置声明 但是只限用类型 其他情况必须包含头文件
1.全部放进头文件.h里称为置入型模型 可以泛化任何类型
2.声明放在头文件 定义放在cpp中 又称显示实例化 编译时会去编译cpp 要使它能找到编译的类型 必须手动告知编译器要泛化的类型 即 template class TemplateClass<T>;
3.export 声明手动导出 称为分离编译模型 但是目前编译器还不支持 至少vs
如果LZ只是要用模板这个类型可以用前置声明 但是只限用类型 其他情况必须包含头文件
#30
路过求分+学习
#31
"如果LZ只是要用模板这个类型可以用前置声明 但是只限用类型 其他情况必须包含头文件"
格式如何写?此方式好像试过会提示识别不了<符号
好像在搜过的相关文章上看到,在别的文件中使用类模版,必须包含这个模版的定义,我去试下
#32
#ifndef
#endif
#endif
#33
Vc6.0下。。亲试。。可编译通过。。。
#34
在一个头文件中用class声明一下另一个头文件中的类,在另一个头文件中include。一般不建议两个类这般联系,应该好好设计下类层次结构。
#35
学习了。。。
#36
#ifndef AAAAA
#define AAAAA
#include "B.h"
class A{...};
#endif
#define AAAAA
#include "B.h"
class A{...};
#endif
#37
前置声明 class T;只是告知编译器 存在这个类型 主要是用于模板 显示实例化
template class TemplateClass<T>;
只要将这句加到T的.h中就行了 但是这样就只能实例化T 不能实例化其他类型
template class TemplateClass<T>;
只要将这句加到T的.h中就行了 但是这样就只能实例化T 不能实例化其他类型