2011-04-05 89 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