代码之家  ›  专栏  ›  技术社区  ›  drahnr

C++类,其基类和循环包含(复制)

  •  0
  • drahnr  · 技术社区  · 15 年前

    文件#1(foo.h):

    #ifndef FOO_H_
    #define FOO_H_
    #include "baseclass.h"
    #include "bar.h"
    class Bar;
    class Foo : public baseclass {
    public:
    bar *varBar;
    };
    #endif
    

    文件#2(bar.h):

    #ifndef BAR_H_
    #define BAR_H_
    #include "foo.h"
    class Foo;
    class Bar {
    public:
    Foo *varFoo;
    };
    #endif
    

    文件#3(baseclass.h):

    #ifndef BASECLASS_H_
    #define BASECLASS_H_
    #include "foo.h"
    class Foo;
    class baseclass {
    public:
    list<Foo*> L;
    };
    #endif
    

    但我在文件#1的第行中得到一个编译错误 class Foo : public baseclass :

    Error: expected class-name before »{« token
    

    class baseclass;

    Error: invalid use of incomplete type »struct baseclass«
    

    所以我的问题是,如何解决基类的循环依赖关系?

    问问你是否明白了什么。我已经准备好尝试改变包含标题的顺序,但到目前为止运气不佳。 谢谢你的提示。

    编辑:注意:我使用的是包含防护装置 EDIT3:添加基类(忘记O.O) EDIT4:现在应该很清楚了,没有任何瑕疵,问题在于这段代码。

    5 回复  |  直到 6 年前
        1
  •  4
  •   RedGlyph sumit sonawane    15 年前

    #ifndef FOO_H_
    #define FOO_H_
    #include "baseclass.h"
    #include "bar.h"
    class Bar;
    class Foo : public baseclass {
    public:
    bar *varBar;
    };
    #endif
    

    #ifndef BAR_H_
    #define BAR_H_
    #include "foo.h"
    class Foo;
    class Bar {
    public:
    Foo *varFoo;
    };
    #endif
    

    大多数编译器(gcc、VC)也接受 #pragma once


    编辑:

    causes the implementation to behave in an implementation-defined manner. Any pragma that is not recognized by the implementation is ignored.

    目前对于C++0x仍然是相同的。

    所以我会坚持第一种老式的方法;-)

        2
  •  3
  •   Pete Kirkham    15 年前

    你似乎已经发布了一个 Bar 委员会成员 Foo 委员会成员 酒吧 包含 酒吧 然后,构建任何一个都不会终止。

    class Foo : public baseclass {
        public:
            Bar varBar;
    };
    
    class Bar {
        public:
            Foo varFoo;
    };
    

    相反,您需要使用指向 至少在其中一种情况下:

    class Bar;
    class Foo : public baseclass {
        public:
            Bar& varBar;
    };
    
    class Bar {
        public:
            Foo varFoo;
    };
    

    由于循环性被破坏,并且您只使用了对对象的引用,因此您不需要拥有所引用类型的完整定义,并且可以使用前向声明。

    Include guards对用户很好,但在开发时尽量不要依赖它们。如果编译器必须检查是否包含了某些内容,那么即使它对guards/pragmas进行了优化,它仍在工作。您确实需要了解什么取决于打破最初的循环,而在文件上设置防护并不能帮助您做到这一点。

        3
  •  2
  •   Billy ONeal IS4    15 年前

    你的头上有防护罩吗?上面的代码递归地包含a.h和b.h,因此定义了一整组头。

    远期宣言 class b; 不再需要 #include "b.h" 在文件1中。同样地, #include "a.h"

        4
  •  2
  •   Zoli    15 年前
    #ifndef _BAR_H_
    #define _BAR_H_    
    #include "baseclass.h"
    
    class Bar;
    class Foo : public baseclass {
    public:
        Bar *varBar;
    };
    
    #endif
    

    如果一个类是前向声明的,并且您只使用指向该类成员的指针或引用,则不需要包含该类的头。另一个文件中的类也是如此。但是,请确保在所有头文件中使用include-guard( #ifndef...#endif )防止在编译过程中包含多个标头。

        5
  •  0
  •   dave4420    15 年前

    baseclass.h 不需要任何东西 foo.h ,所以删除 #include "foo.h" 从…起 基类.h .

    你有一个 Foo Bar 酒吧 . 这是行不通的:你不能把鸡蛋放在盒子里 鸡蛋里的盒子。其中一个或两个应该是指针。