2010-02-17 40 views
8

不完全型的我有彼此依賴兩類:無效使用對於g ++

class Foo; //forward declaration 

template <typename T> 
class Bar { 
    public: 
    Foo* foo_ptr; 
    void DoSomething() { 
     foo_ptr->DoSomething(); 
    } 
}; 

class Foo { 
    public: 
    Bar<Foo>* bar_ptr; 
    void DoSomething() { 
     bar_ptr->DoSomething(); 
    } 
}; 

當我編譯它以g ++,它被給予的「無效使用不完整的類型的」錯誤,但它是在MSVC 10中很好地編譯。 在將聲明和定義保留在一個頭文件中的同時,是否可以解決這個問題? (沒有cpp文件) 如果標準中不允許這樣做,那麼這個MSVC的「錯誤」或「特徵」也是如此?

+0

順便說一句,在Linux上編譯很好。在類聲明的末尾添加分號之後,您是否嘗試將實現移動到cpp文件並在頭中留下聲明?由於Foo和Bar互相引用,會調用DoSomething創建無限循環嗎? – stefanB 2010-02-17 01:19:58

+0

我使用g ++ 4.4.1,它給出錯誤:不完整類型'struct Foo'的無效使用。請不要介意無限循環,我錯誤地讓他們調用相同的方法,但我們可以考慮Foo和Bar類有其他方法。 – leiiv 2010-02-17 01:26:27

+2

G ++是正確的:'DoSomething'是一個非依賴名稱,因爲限定符'foo_ptr->'中沒有任何內容會使其依賴於模板參數。因此,必須查看模板定義時間(但當時,「DoSomething」尚未聲明)。取而代之的是在實例化時間查找相關名稱。由於MSVC++編譯器沒有實現這種兩階段查找,因此它不會在程序中檢測到此錯誤。 – 2010-02-18 15:04:37

回答

8

是的,只需移動方法定義出來的類定義的:

class Foo; //forward declaration 

template <typename T> 
class Bar { 
    public: 
    Foo* foo_ptr; 
    void DoSomething(); 
}; 

class Foo { 
    public: 
    Bar<Foo>* bar_ptr; 
    void DoSomething() { 
     bar_ptr->DoSomething(); 
    } 
}; 

// Don't forget to make the function inline or you'll end up 
// with multiple definitions 
template <typename T> 
inline void Bar<T>::DoSomething() { 
    foo_ptr->DoSomething(); 
} 
+1

因此,如果不將類實現從定義中分離出來,就沒有辦法使它工作。 – leiiv 2010-02-18 01:12:34

+1

@leiiv - 我不知道任何便攜式的方式。但要清楚的是,實現仍然可以在頭文件中進行;不需要新的源文件。 – 2010-02-18 01:18:33

0

看到這個頁面: What is the best way to deal with co-dependent classes in C++?

它應該清理的問題,並提供了一個很好的夫婦解決方案。

+3

只需鏈接到SO上的其他答案應通過評論完成,而不是作爲答案。 – 2010-02-17 01:18:05

+0

好點。我有點忘記了我的急忙。 – 2010-02-17 01:18:54

0

它當您通過模板參數T更換Foo* foo_ptr;讓你得到T* foo_ptr;工作。在這個foo_ptr不一定是一個指針或預定義。

template <typename T> 
class Bar { 
    public: 
    T foo; 
    void DoSomething() { 
     foo.DoSomething(); 
    } 
}; 

class Foo { 
    public: 
    Bar<Foo>* bar_ptr; 
    void DoSomething() { 
     bar_ptr->DoSomething(); 
    } 
};