2011-04-05 85 views
2

有人可以解釋我做錯了什麼嗎?這是我從編譯器得到的錯誤。非模板功能模板類的朋友

非常感謝

1>------ Build started: Project: Ch16, Configuration: Release Win32 ------ 
1> p643_inclusion.cpp 
1> p643_inclusion_main.cpp 
1> p643_print.cpp 
1>p643_print.cpp(5): error C2065: 'T1' : undeclared identifier 
1>p643_print.cpp(5): error C2065: 'T2' : undeclared identifier 
1>p643_print.cpp(6): warning C4552: '<<' : operator has no effect; expected operator with side-effect 
1>p643_print.cpp(7): warning C4552: '<<' : operator has no effect; expected operator with side-effect 
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

p643_inclusion.h

#ifndef P643H 
#define P643H 

template< class T1, class T2> class Car { 

    friend void print (const Car<T1, T2> &c1); 
    private: 
     T1 Wheels; 
     T2 DriversName; 
    public: 
     Car(): Wheels(4), DriversName("None") {} 
     Car(T1, T2); 
}; 



template <class T1, class T2> class Driver { 
    private: 
     T1 Name; 
     T2 Surname; 
    public: 
     Driver(): Name("None"), Surname("None") {} 
}; 


#include "p643_inclusion.cpp" 

#endif 

p643_inclusion.cpp

# ifndef P643CC 
#define P643CC 

#include <iostream> 
#include <string> 
using std::string; 
using std::cout; 
using std::endl; 
#include "p643_inclusion.h" 

template<class T1, class T2> 
Car<T1, T2>::Car(T1 w, T2 d) { 
    Wheels = w; 
    DriversName = d; 
} 

#endif 

p643_print.cpp

#include "p643_inclusion.h" 
template< class T1, class T2> class Car; 

void print (const Car<T1, T2> &c1) { 
    cout << c1.Wheels << endl; 
    cout << c1.DriversName << endl; 
    } 

主要

#include "p643_inclusion.h" 
#include<iostream> 
#include<string> 
using namespace std; 


int main() 
{ 

    Car<int, string> myCar; 
    Driver<string, string> myDriver; 

    print(myCar); 

    return 0; 
} 
+0

包括文件*在* p643_inclusion.h *中的p643_print.cpp *就像您包含'p643_inclusion.cpp'一樣。 – Nawaz 2011-04-05 16:45:47

回答

4

你的函數實際上不是一個非模板函數。

void print (const Car<T1, T2> &c1) { 
    cout << c1.Wheels << endl; 
    cout << c1.DriversName << endl; 
} 

這是錯誤的。你能問自己究竟是什麼T1?和T2


你應該實現這樣的:

template<class T1, class T2> 
void print (const Car<T1, T2> &c1) { 
    cout << c1.Wheels << endl; 
    cout << c1.DriversName << endl; 
} 

而且你應該讓friend爲:

template< class T1, class T2> class Car { 

    //choose different name for type params, because enclosing class 
    //already using T1, and T2 
    template<class U, class V> 
    friend void print (const Car<U, V> &c1); 

    //... 
+0

公平點。感謝你的回覆!所以基本上非模板函數不能使用任何模板參數。只有模板功能可以這樣做。我不知道這一點 - 我的意思是我知道它,但沒有想到直... – RandomCPlusPlus 2011-04-05 16:08:56

+1

@RandomCPlusPlus:是的。模板意味着模板參數! – Nawaz 2011-04-05 16:10:39

+0

嗨,你的評論是非常有幫助的,至少我意識到我的一個錯誤。必須有另一個。我遵循你的建議,但現在我得到這1> p643_inclusion_main.cpp 1> p643_inclusion_main.cpp(13):錯誤C3861:'打印':標識符未找到再次感謝 – RandomCPlusPlus 2011-04-05 16:26:34

2

混合模板和友誼並不像看起來那麼簡單。我的建議是,你定義在類定義中結識的功能,然後你的問題將基本消失:

template <typename T1, typename T2> 
struct test { 
    friend void print(test const & t) { ... }; 
}; 

爲模板test的每個實例,它會聲明和定義(非模板)免費功能這需要一個test對象與觸發模板實例化的相同模板參數實例化。

其它選項(我會留下清晰的這些如果可能的話):

您可以print是一個模板,並聲明模板類模板的一個朋友(全模板):

template <typename T1, typename T2> 
struct test { 
    template <typename U, typename V> 
    friend void foo(test<U,V> const &); // befriend template, all instantiations 
}; 
template <typename T1, typename T2> 
void foo(test<X,Y> const & x) {...} 

這會打開您的內部模板的所有潛在實例,包括可能的特化,您可能不想這樣做。如果你想交好僅該模板的特定實例,你可以這樣做,但它變得更麻煩:

template <typename T1, typename T2> struct test; // forward declaration 

template <typename T1, typename T2> 
void foo(test<T1,T2> const &);     // forward declaration 

template <typename T1, typename T2> 
struct test { 
    friend void foo<T1,T2>(test<T1,T2> const &); // befriend specific instantiation 
}; 

template <typename T1, typename T2> 
void foo(test<T1,T2> const & x) { ... }   // implement 

對於進一步的解釋,你可以看看答案here

+0

啊,打我吧。我只是在看另一個問題,那是什麼? – Potatoswatter 2011-04-05 16:40:05