代码之家  ›  专栏  ›  技术社区  ›  Jon Purdy

解决模板类之间的循环依赖关系

  •  19
  • Jon Purdy  · 技术社区  · 14 年前

    我有两节课, Foo<T> Bar<T> ,派生自 Base . 每个方法都重写一个方法 virtual Base* convert(ID) const ID 是唯一标识 Foo Bar (假装它是一个 enum ). 问题是 Foo::convert() 酒吧 例如,同样地 Bar::convert() . 因为它们都是模板,所以这会导致它们之间的循环依赖关系 Foo.h Bar.h . 如何解决此问题?

    编辑: 转发声明不起作用,因为每个方法的实现都需要另一个类的构造函数:

    :

    #include <Base.h>
    
    template<class T> class Bar;
    
    template<class T>
    class Foo : public Base { ... };
    
    template<class T>
    Base* Foo<T>::convert(ID id) const {
    
        if (id == BAR_INT)
            return new Bar<int>(value); // Error.
    
        ...
    
    }
    

    巴.h :

    #include <Base.h>
    
    template<class T> class Foo;
    
    template<class T>
    class Bar : public Base { ... };
    
    template<class T>
    Base* Bar<T>::convert(ID id) const {
    
        if (id == FOO_FLOAT)
            return new Foo<float>(value); // Error.
    
        ...
    
    }
    

    错误自然是“不完整类型的无效使用”。

    4 回复  |  直到 14 年前
        1
  •  21
  •   Drew Noakes    10 年前

    您需要做的是将类声明与实现分离开来。比如说

    template <class T> class Foo : public Base
    {
        public:
        Base* convert(ID) const;
    }
    
    template <class T> class Bar : public Base
    {
        public:
        Base* convert(ID) const;
    }
    
    template <class T> Base* Foo<T>::convert(ID) const {return new Bar<T>;}
    template <class T> Base* Bar<T>::convert(ID) const {return new Foo<T>;}
    

    这样,在定义函数时就有了完整的类定义。

        2
  •  16
  •   James Curran    14 年前

    (已更新)

    #if !defined(BAR_H_INCLUDED)
    #define BAR_H_INCLUDED
    
    template <class T>
    class Foo;
    
    template <class T>
    class Bar
    {
        /// Declarations, no implementations.
    }    
    
    #include "Foo.h"
    
    template <class T>
    Base* Bar<T>::Convert() {  /* implementation here... */ }
    #endif
    
        3
  •  13
  •   Mazyod    9 年前

    template <class T>
    class X;
    

    是非常好的模板类转发声明。

        4
  •  10
  •   Vijay Rao    13 年前

    t1.hh公司

    #ifndef S_SIGNATURE
    #define S_SIGNATURE
    
    struct G; // forward declaration
    
    template<typename T>
    struct S {
      void s_method(G &);
    };
    
    #include "t2.hh" // now we only need G's member declarations
    
    template<typename T>
    void S<T>::s_method(G&g) { g.g_method(*this); }
    
    #endif
    

    t2.hh小时

    #ifndef G_SIGNATURE
    #define G_SIGNATURE
    
    template<typename T>
    struct S; // forward declaration
    
    struct G {
      template<typename T>
      void g_method(S<T>&);
    };
    
    #include "t1.hh" // now we only need S' member declarations
    
    template<typename T>
    void G::g_method(S<T>& s) { s.s_method(*this); }
    
    #endif
    

    t、 抄送

    #include "t1.hh"
    #include "t2.hh"
    
    S<int> s;
    G g;
    
    int main(int argc,char**argv) {
      g.g_method(s); // instantiation of G::g_method<int>(S<int>&)
    }