矩陣就不用再解釋了,寫成泛型主要是為了幾個方便:
1、方便在棧上分配空間。由於維度在編譯期已知,所以可以做到在棧上分配空間。當然如果這個物件是new出來的,自然是在堆上分配,這裡說的是在棧上分配這個物件時,矩陣元素所占用的空間也在棧上分配。
2、方便在編譯期檢查非法的矩陣運算。c++模板的強大推導能力可以在編譯期推導出結果矩陣的維度。
3、泛型類在方法內聯上具有優勢。
這個矩陣類為了能夠直接從陣列賦值,使用了乙個arrayporxy類(可參考《imperfect c++》)。
**如下:
template
<
class
t, int
d1,
intd2=1
>
class
arrayproxy
arrayproxy(t (
&value)[d1
*d2])
: data(value)t*
getdata()
const};
這個只是簡單的實現。
因為我基本上不使用這個矩陣類,所以只完成幾個簡單功能:
1、從陣列賦值:
int a[3] = , };
matrixm1(a); 或
int a = ;
matrixm1(a);
matrixm2(a);
matrixm3(a);
matrixm4(a);
2、矩陣乘法:
matrixm1;
matrixm2;
// m1 * m2 <== 編譯錯誤,維度不匹配
matrixm3;
matrixm4 = m1 * m3; // <== 合法
// m3 * m1; // <== 編譯錯誤,維度不匹配
原始碼如下:
template
<
class
t, int
r, int
c>
class
matrix
matrix(
const
matrix
&rhs)
matrix
&operator=(
const
matrix
&rhs)
public
:matrix(
const
arrayproxy
<
t,r,c
>&
arr)
~matrix(
void
)public:t
get(
intr,
intc)
const
void
set(
intr,
intc, t v)
intgetcols ()
const
intgetrows ()
const
bool
operator==(
const
matrix
&rhs) const
bool
operator!=(
const
matrix
&rhs) const
};template
<
class
t, int
r, int
c, int
c1>
matrix
<
t,r,c1
>
operator*(
const
matrix
<
t,r,c
>&
lhs,
const
matrix
<
t,c,c1
>&
rhs)
result.
set(r,c,value);}}
return
result;}
測試**:
intmain()
inta =;
matrix
<
int, 3,
4>
m5(a);
intb[3][
4] =,
,};matrix
<
int, 3,
4>
m6(b);
matrix
<
int, 3,
4>
m7(m5);
matrix
<
int, 3,
4>
m8 =
m5;matrix
<
int, 3,
4>
m9;m9
=m5;
for(
inti=0
; i<
3; i++)
for(
intj=0
; j<
4; j++)
//維數不匹配,編譯錯誤
//matrixm10 = m9;
intc[2]
=, };
//陣列大小不匹配,編譯錯誤
//matrixm10(c);
intd =;
//陣列大小不匹配,編譯錯誤
//matrixm11(d);
//乘法維數不合適,無法相乘
//m1 * m2;
matrix
<
int,4,
3>
m12;
//匹配,可以相乘
matrix
<
int, 3,
3>
m13
=m1
*m12;
matrix
<
int, 8,
3>
m14;
//無法相乘
//matrixm15 = m1 * m14;
//可以相乘
matrix
<
int, 8,
4>
m15
=m14
*m1;
}, };
matrix
<
int, 2,
5>
m1(a);
intb[5][
3] =, , , , };
matrix
<
int, 5,
3>
m2(b);
intc[2][
3] =, };
matrix
<
int, 2,
3>
m3(c);
matrix
<
int, 2,
3>
m4 =
m1 *
m2;assert(m4
==m3);
cout
<<
m4.get(0
,0) <<
endl;
}return0;
} 補充:
1、加法、減法只需要2個矩陣維度相同即可。
template
<
class
t, class
r, class
c>
matrix
<
t,r,c
>
operator+(
const
matrix
<
t,r,c
>&
lhs,
const
matrix
<
t,r,c
>&
rhs)
2、由於1x1的矩陣可以看成乙個標量,矩陣與標量運算結果維數與原矩陣相同,可以過載來實現。
template
<
class
t, class
r, class
c>
matrix
<
t,r,c
>
operator*(
const
matrix
<
t,r,c
>&
lhs,
const
matrix
&rhs)
3、由於型別泛化,可能某些合理的運算無法進行,比如float型矩陣,與乙個int型標量運算等。這些最好是借助型別萃取等手段,推導出運算以後的型別。(c++0x中包含自動獲取運算結果型別的關鍵字typeof,等幾年就可以用了:)。gcc編譯器中已有實現,不過似乎有bug)。
4、其它。泛型實現可能會有一些考慮不周的地方,強型別有強型別的好處,不過必須要有完整的泛型演算法支撐,否則難以使用。也可以把泛型矩陣類從乙個普通矩陣類派生,這樣更容易寫出通用演算法,不過在實現上可能要借助於執行期多型,對於矩陣類來說並不合適。
5、其它。。前面說c++的模板相當強大,d語言模板到目前為止似乎已經完全實現了c++模板的功能,還增加了一些比如字串值參模板等特性,比c++模板功能更多。在**編寫上,由於可以編寫靜態判斷語句(編譯期)以及靜態斷言,編寫模板比c++更容易。有時間可以試試用它寫個矩陣類,純粹是興趣,這些東西真的很難用到,現成的庫也挺多。
6、其它。。。c++0x要提供「template typedef」,也就是可以這樣定義:
template typedef matrixmatrixint; // 定義型別,維度不定
template typedef matrixmatrix4x4; // 定義維度,型別不定
由此可以出定義行向量、列向量、標量等,當然實際使用起來可能沒那麼舒服了。
泛型 泛型類 泛型方法 泛型擦除
1 是什麼?一種允許我們在不確定引數型別時候使用的型別。例如我不知道a方法應該會傳string還是int,我就用個泛型先佔坑。2 為什麼要用泛型?泛型可以在編譯期自動確定具體型別,檢查型別是否匹配,可以提高 的重用率,減少冗餘編碼。3 泛型與object的區別?像上面說的我不知道方法a的引數型別,其...
泛型之泛型類
public class a 構造引數型別上使用泛型 public a t t 方法返回值上使用泛型 public t gett 方法的引數上使用泛型 這是泛型類的方法,而不是泛型方法 public void sett t t 方法的返回值和引數型別上使用泛型 public t foo t t pu...
泛型之泛型類
public class a 構造引數型別上使用泛型 public a t t 方法返回值上使用泛型 public t gett 方法的引數上使用泛型 這是泛型類的方法,而不是泛型方法 public void sett t t 方法的返回值和引數型別上使用泛型 public t foo t t pu...