关于前置声明

来源:互联网 发布:网络诈骗的种类有哪些 编辑:程序博客网 时间:2024/05/13 17:36

部分治疗来源于:http://www.cnblogs.com/clever101/archive/2009/10/31/1593533.html                 http://blog.csdn.net/yunyun1886358/article/details/5672574

当两个类出现相互应用时:比如

#pragma once

#include "B.h"

class A

{

        B* pointB;

}              //A.h

////////////////////////////////////////////////////////////////////

#pragma once

#include"A.h"

class B

{

        A* pointA;

}            //B.h

//////////////////////////////////////////////////////////////



此时,会在两个类的头文件出现相互包含头文件,如果没有条件编译命令(#pragma one)对编译器而言,会出现头文件相互包含的死循环,【编译器为了避免循环依赖的问题(比如说A.cpp在进行编译的时候,由于包含了A.h,便进行A.h的编译,但A.h包含了B.h,可是B.h又包含了A.h),编译器在进行A.h的时候,可能对A.h做了记录,假定A.h已编译(但实际没有),然后就进入B.h的编译中,在B.h中,由于A.h 并未被编译,所以出现了无法识别A类的问题,进而编译出错】。当存在条件编译时(#pragma once),先编译A.h, 然后转到B.h ,然后又转到A.h,此时,#pragma once告诉编译器,此文件A.h已经被编译了(实际上并没有),此时也出现了无法识别A类的编译错误。


这是就是前置声明出场了,在头文件中用前置声明替换掉了文件包含!如下:

#pragma once

class B;              //此次被替换

class A

{

        B* pointB;

}              //A.h

////////////////////////////////////////////////////////////////////

#pragma once

#include"A.h"

class B

{

        A* pointA;

}            //B.h

//////////////////////////////////////////////////////////////

这样,就避免了编译出错,前置声明告诉编译器,B是一个类,注意:此时的B是不完整类型,因为不知道类的具体内容!由于B是一个不完整的类型,

重点:::所以在A.h中只能存在B的指针或引用!!!!!!!!!!不能使用B的方法,当然也包括B的析构函数了



对于友元函数的解决方案,参见《c++ primer plus》  p607

class Tv

{

   friend void Remote::set_cha(Tv& t, intc);

}

为了避免循环依赖,解决方法是:

class Tv;             //forward declaration

class Remote{**************};

class Tv{**************};

注意:此时的Remote类定义中不能存在Tv类的方法(即把内联函数直接写在类中).

但可以把内联函数方法定义在Tv类定义的后面,这样仍然实现了内联函数功能.

比如:

class Tv;             //forward declaration

class Remote{**************};

class Tv{**************};

inline bool Remote::volup(Tv& t)  {return t.volup()}


如此相似的类型还有很多,可以自行判断

//////////////////////////////完




0 0
原创粉丝点击