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