前瞻声明与包含

Sii*_*Sii 19 c++ class forward-declaration

考虑以下两种情况(编辑只是为了完成整个问题并使其更清晰)

案例1 :(如下面正确提到的那样编译)

//B.h
#ifndef B_H
#define B_H
#include "B.h"

class A;

class B { 
        A obj;
        public:
        void printA_thruB();

         };  
#endif

//B.cpp
#include "B.h"
#include <iostream>

void B::printA_thruB(){
        obj.printA();
        }   


//A.h;
#ifndef A_H
#define A_H

#include "A.h"

class A { 
        int a;
        public:
        A();
        void printA();

         };  
#endif   

//A.cpp                           
#include "A.h"                    
#include <iostream>               

A::A(){                           
        a=10;                     
        }                         

void A::printA()                  
{                                 
std::cout<<"A:"<<a<<std::endl;    
}  


//main.cpp
 #include "B.h"
  #include<iostream>
 using namespace std;

 int main()
 {
 B obj;
 obj.printA_thruB();
 }
Run Code Online (Sandbox Code Playgroud)

案例2 :(唯一的修改......没有编译错误)

//B.h

#include "A.h" //Add this line
//class A;     //comment out this line
Run Code Online (Sandbox Code Playgroud)

让我们假设A.cpp和B.cpp都被编译在一起.上述两种情况是否存在差异?是否有理由更喜欢一种方法而不是另一种方法?

编辑:那么我如何使场景1工作.

Dre*_*all 13

编译B.cpp时,情况1将产生"不完整类型"错误.因为B类包含A类对象,所以A类的定义(特别是大小)必须在B类定义之前完成.

或者,您可以选择使some_variable成为A类的指针或引用,在这种情况下,您的前向声明在Bh中就足够了.您仍然需要B.cpp中A的完整定义(假设您实际使用了成员函数/数据).

  • 澄清.如果您尝试在A上调用任何方法,则情况1将仅产生编译错误.在这种情况下,它应该给出错误,因为您将隐式调用构造函数.但是在不同的场景中,如果B的一个方法只是接收到一个指向A对象的指针,然后将其传递给B负责之外的其他方法/函数,那么编译器就可以不知道A的定义了. (3认同)

lia*_*iaK 11

前向声明不能替代Header文件包含.

正如名称本身所暗示的那样,前向声明只是一个Declaration 而不是定义.

因此,您将声明编译器说它是一个类,我只是在这里声明它并将在何时使用它时为您提供定义.因此,通常您forward declare在Header文件和#include.cpp文件中,您将使用前向声明的类的成员.

通过这样做,你所做的是,无论你在哪里包括头文件,都只会有一个类的声明而不是整个内容#included......

但话说回来,当编译器需要定义类时,应该是#included..

因此,在您的情况下A obj;需要定义,class A因此您应该#include..

我自己在这里问了一个类似的问题,另一个 类似的问题也有一个很好的答案......

希望能帮助到你..