鉴于以下类在两个单独的头文件中,并且可以按任何顺序出现:
//TestB.h
class TestB; //Forward declaration for a later operator= in a centralised header
class TestA
{
const TestA&operator=(const TestB); //defined in Test.h
};
和
//TestA.h
class TestA; //Forward declaration for a later operator= in a centralised heaer
class TestB
{
const TestB&operator=(const TestA); //defined in Test.h
};
如何避免原型冲突?
非常感谢帮助。
我绝对向大家道歉!我原本打算在那里引用(运算符中的&符号=参数 - 我永远不会通过复制条形简单的POD)并且只是关于原型冲突的问题!我想它会证明校对的重要性!鉴于原始(我的错误)背景,我接受了答案。
我只是转过身几分钟,并没有意识到错误!
答案 0 :(得分:4)
您将对类的引用作为参数传递。这样,可以在不知道另一个的情况下声明类及其成员函数。
//TestB.h
class TestB; //Forward declaration for a later operator= in a centralised header
class TestA
{
const TestA&operator=(const TestB &); //defined in TestB.h
};
和
//TestA.h
class TestA; //Forward declaration for a later operator= in a centralised heaer
class TestB
{
const TestB&operator=(const TestA *); //defined in TestA.h
};
在此之后,您必须在TestA.cpp和TestB.cpp文件中包含TestA.h和TestB.h才能定义这些成员函数。
答案 1 :(得分:4)
我的原始答案似乎完全错误。
检查所有头文件中是否包含防护,这样就不会产生无限的包含链。然后在每个实现中包含标题:
// A.cpp
#include "A.h"
#include "B.h" // for complete type TestB
const TestA & TestA::operator=(const TestB) { /* ... */ }
// B.cpp
#include "B.h"
#include "A.h" // for complete type TestA
const TestB & TestB::operator=(const TestA) { /* ... */ }
请注意,这样的结构会产生一种奇怪的设计状况,任何希望致电运营商的TestA
或TestB
消费者必须始终同时包含A.h
和{{1} },这是非常精细的,但也有点意外。可能有必要添加一个供客户端使用的中间头文件,其中包含两个头文件,或者将相互内容(带有警卫!)添加到头文件本身。
你无法以编写它的方式解决这个问题,因为你有一个平坦的递归无限依赖。
通常这样做的方法是通过参考而不是通过副本传递参数,因为通过引用传递而不是需要知道完整类型:
B.h
答案 2 :(得分:1)
这些标头中没有实际问题,只要它们只声明成员函数并且不提供定义。也就是说,如果成员函数的定义位于包含两个标题的.cpp文件中,并且标题中没有对任一函数的调用,那么它应该可以正常工作。
有一种常见的误解是你不能使用具有前向声明类型的任何看似 value 的东西,事实是你不能创建该类型的对象或创建该类型的成员变量,但可以声明按值获取或返回类型的函数。
另一方面,你不能定义或调用这些函数,因为这需要创建不完整的对象类型。
答案 3 :(得分:0)
前向声明仅适用于声明指针和对类型的引用...它们不能用于实际的复制操作以及将类实例声明为非静态类数据成员。如果您尝试这样做,编译器将为不完整类型提供错误,因为没有足够的信息来为编译器提供有关实际类型组成的信息(即,它有多大等等)。 ),以便它可以构造主类或确定分配给一个类的方法参数的堆栈空间。