2013-04-08 68 views
2

我使用CRTP模式來創建一個接口,其他類將從中獲得。CRTP,前置聲明和模板在cpp文件

在我向前聲明結構(重要,因爲我不想拖在接口其他的東西)的接口,但我包括它在其中定義了接口cpp文件定義。

Interface.h

#ifndef INTERFACE_H_INCLUDED 
#define INTERFACE_H_INCLUDED 

// forward declaration 
class ForwardDecl; 

template <class Derived> 
class Interface 
{ 
public: 
    ForwardDecl interfaceMethod(); 

}; 

#endif // INTERFACE_H_INCLUDED 

ForwardDecl.h

#ifndef FORWARDDECL_H_INCLUDED 
#define FORWARDDECL_H_INCLUDED 

struct ForwardDecl 
{ 
    ForwardDecl(int i):internal(i) 
    {} 

    int internal; 
}; 

#endif // FORWARDDECL_H_INCLUDED 

Interface.cpp

#include "Interface.h" 
#include "ForwardDecl.h" 

template<class Derived> 
ForwardDecl Interface<Derived>::interfaceMethod() 
{ 
    return static_cast<Derived *>(this)->implementation_func(); 
} 

這是我mplementation它實現了接口

Implementation.h

#ifndef IMPLEMENTATION_H_INCLUDED 
#define IMPLEMENTATION_H_INCLUDED 
#include "Interface.h" 
class ForwardDecl; 

class Implementation: public Interface<Implementation> 
{ 
    friend class Interface<Implementation>; 
private: 
    ForwardDecl implementation_func(); 

}; 


#endif // IMPLEMENTATION_H_INCLUDED 

Implementation.cpp

​​

和主文件

#include <iostream> 
#include "Implementation.h" 
#include "ForwardDecl.h" 
using namespace std; 

int main() 
{ 
    Implementation impl; 

    ForwardDecl fd = impl.interfaceMethod(); 
    cout << fd.internal << endl; 
    return 0; 
} 

我得到鏈接錯誤s VS和GCC。

任何解決方法?謝謝。

+0

[爲什麼模板只能在頭文件中實現?](http:// stackoverflow。com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – WhozCraig 2013-04-08 13:32:12

+0

在接口中進行前向聲明工作是這裏的主要觀點,如果它不是我想要的將所有內容移動到頭文件中。 – farnsworth 2013-04-08 13:35:21

+0

你想要做什麼(如果我理解它,哪些是有可能的),可能有模板*接口*定義和指針,但是像這樣的實例級別,我很難看到它的工作。 – WhozCraig 2013-04-08 13:37:27

回答

1

。在你的非常做法有缺陷,你有一個公共函數返回一個ForwardDecl實例,讓每一個客戶想要使用此功能,還必須包括該類型的根據定義,這意味着你可以從這種類型的公共開始。這包括使內聯函數定義,這將解決您的鏈接器問題。但是,如果你真的想要隱藏那個結構的內容,並且你確信客戶端不需要它,你可以聲明它,然後傳遞這樣一個結構的引用(或者指針,但是原始指針是邪惡,雖然不像#macros那樣處於同一個邪惡聯盟中)。在這種情況下,我仍然會內聯函數定義。

如果你真的,真的想不使函數內聯,也可以顯式實例爲你所需要的類型的函數模板。你會在添加的模板的.cpp文件類似template class Interface<int>;(我不記得確切的語法,所以採取,隨着芙蓉DE SEL幾片,檢查了C++ FAQ at parashift.com for more info)結束。這使得該模板不太普遍,因爲它需要調整任何類型,你可以使用它,但它可能是一些角落案件的方法。

+0

yup在閱讀parashift的常見問題解答之後修正了一段時間,因爲你的回答是正確的,你會得到要點:) – farnsworth 2013-04-08 21:21:24

1

的函數模板和類模板的成員函數的定義需要在實例化這些模板所有翻譯單元可見。也就是說,不應將模板定義放在.cpp文件中,這意味着您需要將Interface.cpp的內容向上移動到Interface.h

+0

是的,但如果我這樣做,我不得不#include「ForwardDecl.h」**這**是我想要避免的。 – farnsworth 2013-04-08 13:31:58