程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++中模板類使用友元模板函數 和友員非模版函數!使用不當出現編譯錯誤:無法解析的外部符號…

C++中模板類使用友元模板函數 和友員非模版函數!使用不當出現編譯錯誤:無法解析的外部符號…

編輯:關於C++

在c++海大本科課程設計的最後章節(模板使用 )中涉及到了在Mat類模板中定義友元函數friend Mat operator+(Mat &m, T num);//所有元素加上同一數值;

聲明在類中進行如上的聲明,定義在類外進行模板函數的定義,鏈接報錯:

error LNK2001: 無法解析的外部符號 "class Mat __cdecl operator+(class Mat &,double)" (??H@YA?AV?$Mat@N@@AAV0@N@Z)
1>D:\Installation Package\VC6cn\MyProjects\overload_abstract_template\template\Debug\template.exe : fatal error LNK1120: 1 個無法解析的外部命令

 

對在類模板中的友元函數operator+聲明前加上一句:template< typename T> 就可以正常運行了,那麼究其原因,下面對類模板的友元函數進行了總結整理:

在類模板中可以出現三種友元聲明:
(1)普通非模板類或函數的友元聲明,將友元關系授予明確指定的類或函數。
(2)類模板或函數模板的友元聲明,授予對友元所有實例的訪問權。
(3)只授予對類模板或函數模板的特定實例的訪問權的友元聲明。

要注意的是,友元函數並非成員函數,是改變了它對類成員的訪問權限。

(1)沒有什麼好說的,如:

template

class A{

friend void fun();

//...

};
此例中fun可訪問A任意類實例中的私有和保護成員

(2)

template

class A{

template

friend void fun(T u);

//...

};

這時友元使用與類不同的模板形參,T可以是任意合法標志符,友元函數可以訪問A類的任何類實例的數據,即不論A的形參是int,double或其他都可以。

(3)

template

class A{

friend void fun(T u);

//...

};

此時fun只有訪問類中特定實例的數據。換句話說,此時具有相同模板實參的fun函數與A類才是友元關系。即假如調用fun時其模板實參為int,則它只具有A的訪問權限。當然friend void fun(T u);中<>中的T可以是任意類型,比如int,double等

回到原問題,按(3)可改為:
template class List{
friend std::ostream& operator << (std::ostream& os,const List& slist);
//……
};

按(2)可改為:

template class List{

template
friend std::ostream& operator << (std::ostream& os,const List& slist);
//……
};
在這裡其實兩者實現的最終效果一樣的,因為調用輸出運算符時需要訪問的類實例的對象是它本身,所以形參T在第一種改法中一定匹配。


  

對類建立友元函數很容易。但是遷移到模板上卻容易出現讓人摸不著頭腦的連接錯誤。
層次不夠,不做分析,單純介紹兩種為類模板定義友元函數的方法

  1 封閉型

C++中模板類使用友元模板函數template<typenameT>
C++中模板類使用友元模板函數classMyClass
C++中模板類使用友元模板函數{
C++中模板類使用友元模板函數friendvoidfunction(MyClass<T>&arg)
C++中模板類使用友元模板函數{
C++中模板類使用友元模板函數C++中模板類使用友元模板函數
C++中模板類使用友元模板函數}
C++中模板類使用友元模板函數};   要點:友元函數定義在模板體內。

2 開放型
C++中模板類使用友元模板函數template<typenameT>
C++中模板類使用友元模板函數classMyClass
C++中模板類使用友元模板函數{
C++中模板類使用友元模板函數template<typenameC>
C++中模板類使用友元模板函數friendvoidfunction(MyClass<C>&arg);
C++中模板類使用友元模板函數};
C++中模板類使用友元模板函數
C++中模板類使用友元模板函數template<typenameC>
C++中模板類使用友元模板函數voidfunction(MyClass<C>&arg)
C++中模板類使用友元模板函數{
C++中模板類使用友元模板函數C++中模板類使用友元模板函數
C++中模板類使用友元模板函數}   要點:模板體內要另建模板。
  
  3 告訴編譯器聲明的設個是模板
C++中模板類使用友元模板函數#include
C++中模板類使用友元模板函數usingnamespacestd;
C++中模板類使用友元模板函數
C++中模板類使用友元模板函數template<typenameT>
C++中模板類使用友元模板函數classA
C++中模板類使用友元模板函數{
C++中模板類使用友元模板函數friendostream&operator<<<T>(ostream&,constA<T>&);
C++中模板類使用友元模板函數};
C++中模板類使用友元模板函數
C++中模板類使用友元模板函數template<typenameT>
C++中模板類使用友元模板函數ostream&operator<<(ostream&output,constA<T>&a)
C++中模板類使用友元模板函數{
C++中模板類使用友元模板函數output<<"重載成功"<<endl;
C++中模板類使用友元模板函數returnoutput;
C++中模板類使用友元模板函數}
C++中模板類使用友元模板函數
C++中模板類使用友元模板函數intmain()
C++中模板類使用友元模板函數{
C++中模板類使用友元模板函數A<int>a;
C++中模板類使用友元模板函數cout<<a;
C++中模板類使用友元模板函數}
要點:顯示地在重載的運算符或者函數後面加上模板聲明< T >,告訴編譯器友元函數是一個類型一致的模板。

建議:
如果希望使用函數與模板特化的類型相對應,則使用方法3(模板顯示聲明)
如果希望使用函數與模板特化的類型相獨立,則使用方法2(二重模板)
簡短的內聯函數使用方法1
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved