Effective C++ ——如果要爲所有參數隱形轉換,需要non-member

effective c++ 條款46
總結:

  1. 如果需要爲某個函數所有參數(包括This指針所指的隱形參數)進行類型轉換,則需要這個函數是non-member
  2. 普通函數會發生隱式類型轉換
  3. 函數模板自動類型推導不發生隱式類型轉換(可以是把5調用構造,隱形轉換成testmultiply類型)
  4. 函數模板顯示指定類型發生隱式類型轉換
  5. == 重載函數,只能有0個或者1個參數,如果要寫萬能*,必須寫在類外,即是non-member,或者寫在類中,並使用friend==
  6. 直接在友元函數內部, 實現代碼(inline);參考鏈接
  7. 在友元函數內部, 實現一個模板函數, 在把模板函數在外部實現.
  8. testmultiply mul3 = 5 * mul1;中,需要先把5隱形轉換成testmultiply,再走*,但是模板類不支持隱形推導,但是這裏因爲mul1的類型爲testmultiply,推導出類模板的T,然後就可以進行隱形類型推導!這裏使用友元的目的有兩個,1是調用私有變量,2是爲了讓mul1的T能作用在class中所有的T上,推導出T,是的模板變成一個特定的類,幫助完成隱形轉換!3、友元中函數體必須在內部,link不到在外面定義的模板函數體,但是能鏈接到確定的函數!
  9. 接着8,如果 testmultiply mul3 = 5 * mul1;,那麼推導出U爲int,但是不代表templateclass testmultiply的T爲U,testmultiply(T i):a(i){}的T不知道,所以推導不出來。想要隱形推導,必須在class內部函數中!!!!

template< class U>
const testmultiply operator*(const testmultiply& te1, const testmultiply& te2)
{
return testmultiply(te1.a*te1.a);
}
在這裏插入圖片描述

代碼1


class testmultiply
{
public:
   testmultiply()=default;
   testmultiply(int i):a(i){}
   const testmultiply operator*(const testmultiply& te){this->a = this->a * te.a; return *this;}
private:
   int a;
   friend const testmultiply operator*(const testmultiply& te1, const testmultiply& te2);
};
 
const testmultiply operator*(const testmultiply& te1, const testmultiply& te2)
{
   testmultiply te;
   te.a = te1.a * te2.a;
   return te;
   }
int main()
{
   testmultiply mul1(10);
   testmultiply mul2 = mul1 * 5;  //5可以隱形轉換
   testmultiply mul3 = 5 * mul1; //如果常規轉換不行,因爲5沒有this,所以需要全局的*,因爲對象是private所以需要friend

代碼2

template<class T>
class testmultiply
{
public:
   testmultiply()=default;
   testmultiply(T i):a(i){}
   const testmultiply operator*(const testmultiply& te){this->a = this->a * te.a; return *this;}
   friend const testmultiply operator*(const testmultiply& te1, const testmultiply& te2);
private:
   T a;
   
};
template<class T>
const testmultiply<T> operator*(const testmultiply<T>& te1, const testmultiply<T>& te2)
{
   testmultiply<T> te;
   te.a = te1.a * te2.a;
   return te;
   }
int main()
{
   testmultiply<int> mul1(10);
   testmultiply<int> mul2 = mul1 * 5;
   testmultiply<int> mul3 = 5 * mul1; //注意模板類不能自動類型推導,5不能推導出T的類型int,需要mul1推導出T,然後走構造,再重載*

代碼3

template<class T>
class testmultiply
{
public:
   testmultiply()=default;
   testmultiply(T i):a(i){}
   const testmultiply operator*(const testmultiply& te){this->a = this->a * te.a; return *this;}
   

   T a;
private:
 friend const testmultiply<T> operator*(const testmultiply<T>& te1, const testmultiply<T>& te2);
 //或者在這裏寫明{return testmultiply<int>(te1.a*te1.a);}
};

template<class U>
const testmultiply<U> operator*(const testmultiply<U>& te1, const testmultiply<U>& te2)
{
   return testmultiply<U>(te1.a*te1.a);
   }
   
const testmultiply<int> operator*(const testmultiply<int>& te1, const testmultiply<int>& te2){return testmultiply<int>(te1.a*te1.a);};
int main()
{
   testmultiply<int> mul1(10);
   testmultiply<int> mul2 = mul1 * 5;
   testmultiply<int> mul3 = 5 * mul1; //

代碼4

#include<bits/stdc++.h>
using namespace std;

template<class T>
T add(T a,T b)
{
    return a + b;
}

int padd(int a,int b)
{
    return a + b;
}

//普通函數會發生隱式類型轉換
//函數模板自動類型推導不發生隱式類型轉換
//函數模板顯示指定類型發生隱式類型轉換
int main()
{
    int a = 1,b = 2;
    char c = 'a';
    cout << padd(a , b) << endl;
    cout << padd(a , c) << endl;
    cout << add(a,b) << endl;
    //cout << add(a,c) << endl;//函數模板自動類型推導不發生隱式類型轉換

    cout << add<int>(a,b) << endl;
    cout << add<int>(a,c) << endl;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章