C++类的原型冲突

C++类的原型冲突

问题描述:

鉴于以下类是两个独立的头文件,并可以以任意顺序出现:C++类的原型冲突

//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 
}; 

如何避免原型冲突?

帮助表示赞赏。

我绝对向大家道歉!我原本打算在那里引用(operator = arguments中的&符号 - 我绝对不会通过复制bar简单POD来传递),而仅仅是关于原型冲突的问题!我想这表明证明阅读的重要性!我已经接受了原来的(我错误的)背景下的答案。

我只是转过身去了几分钟,并没有意识到错误!

+1

你是什么意思“原型冲突”? –

+2

这里没有错 - 这将工作正常。您需要更好地解释错误,并使用真实的代码。 –

+1

@Als:你可以通过值声明不完整类型的函数;直到类型定义之后才能定义或调用它们。 –

您将对类的引用作为参数传递。这样,一个类和它的成员函数可以在不知道另一个的情况下被声明。

//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.h和TestB.h两个TestA.cpp和TestB.cpp文件能够定义这些成员功能。

+0

没有必要改变语义,只要你不尝试*定义*或者你可以**声明函数来获取或返回一个*不完整类型* *调用*这些函数。 –

我原来的答案似乎是完全错误的。

检查您是否在所有头文件中都包含了警卫,这样您就不会收到无限的包含链。然后,包括在每一个执行标题:

// 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) { /* ... */ } 

请注意,这样的结构能产生好奇的设计情况要么TestATestB的任何消费者谁希望呼叫话务员必须始终包含既有A.hB.h,这是非常细微的,但也有点意外。为包含两个头文件的客户端添加一个中间头文件可能是值得的,或者为头文件本身添加相互包含(带有警卫!)。


你不能在你写的方式解决这个问题,因为你有一台出无限递归的依赖。

你平时做到这一点是通过参考,而不是复制来传递参数,因为通过引用传递的方式确实需要完整的类型的知识:

const TestA & operator=(const TestB &); 
            ^^^^^ 
            vvvvv 
const TestB & operator=(const TestA &); 

+2

即使参数类型不完整,您也可以声明以值为参数的函数。直到类定义之后,才能定义该函数。 –

+0

@Mike:我很惊讶,我真的认为这是不允许的! –

+0

@Kerrek SB:只要函数在头文件中没有* defined *或* called *,甚至不需要添加循环包含,并且* call *或* define这些成员的翻译单元函数包含两个头文件。 –

前向声明仅适用于声明类型的指针和引用......它们不能用于实际的复制操作,也不能用于将类实例声明为非静态类数据成员。如果你试图这样做,编译器会给你一个不完整类型的错误,因为没有足够的信息给编译器提供有关实际类型组成的信息(例如它有多大等等)。 ),以便它可以构造主类或确定分配给类方法参数的多少堆栈空间。

那儿有头没有实际的问题,只要他们只声明成员函数,不提供定义。也就是说,如果成员函数的定义在包含头文件的.cpp文件中,并且在头文件中没有对任何函数的调用,它应该可以很好地工作。

有一种普遍的误解,认为你不能使用任何看起来像与前声明的类型,但事实是,你不能创建该类型的对象或创建该类型的成员变量,但是你可以通过值声明或返回这些类型的函数

你不能,在另一方面,定义呼叫这些功能,因为这将需要不完全类型的对象的创建。