C++向上1【汎用プログラミング】関数テンプレート類テンプレート
22774 ワード
【転載お断り】
【汎用プログラミング】
関数テンプレート
なぜ関数テンプレートがあるのか
現象:
関数のビジネスロジックと同様
関数のパラメータタイプが異なります
【最も一般的】関数テンプレートの明示的な呼び出し
【非常用】タイプ導出
複数のパラメータ、パラメータ定義に使用する必要があります
関数テンプレート、intタイプ配列、char文字列ソートを実現するには:
関数テンプレートと一般関数の本質的な違い
関数テンプレートと一般的な関数を組み合わせた呼び出し型の研究:
C++はどのように関数テンプレートメカニズムをサポートしますか?
関数テンプレートメカニズムの結論
クラステンプレート
クラステンプレートの定義
クラステンプレートの関数としてのパラメータ
クラステンプレートのパイ生成汎用クラス
テンプレートクラスのパイ生成テンプレートクラス
複数クラス、すべての関数がクラスの内部に書き込まれ、演算子がウォーミングアップを再ロードします.
複数クラス、すべての関数がクラスの内部に書かれ、クラステンプレート
【プレゼンテーション】Friend関数を悪用した結果-通常のコード準備
複数クラス、すべての関数がクラスの内部に書かれています(CPP 1つ):問題が投げ出されます
テンプレート関数が友元関数に遭遇した場合、問題は解決されます.
友元関数の乱用の結果
【結論】:友元関数は不要、友元関数は不要
【結論】テンプレート類のcppファイルと.hヘッダファイルを別々に書く場合は、cppファイルも含めます
クラステンプレートにstaticメンバー変数がある場合.クラステンプレートの実質的な分析から、コンパイラは自動的に私たちのために2つのクラスに書きます.
クラステンプレート配列の例
クラステンプレート構造体ケース
ジョブ:
-------------------------------------------------------------------------
【なぜ関数テンプレートがあるのか】
現象:
関数のビジネスロジックと同様
関数のパラメータタイプが異なります
【最も一般的】関数テンプレートの明示的な呼び出し
【非常用】タイプ導出
複数のパラメータ、パラメータ定義に使用する必要があります
関数テンプレート、intタイプ配列、char文字列ソートを実現するには:
関数テンプレートと一般関数の本質的な違い
関数テンプレートと一般的な関数を組み合わせた呼び出し型の研究:
【補足】同じ役割ドメインでは、関数の再ロードが発生します
C++はどのように関数テンプレートメカニズムをサポートしますか?
アセンブリにコンパイル:
クラステンプレート:
クラステンプレートは、クラスに必要なデータのタイプパラメータ化を実現するために使用されます.
クラステンプレートは配列、テーブル、図などのデータ構造を表す上で特に重要であり、
クラステンプレートの定義
クラス末の使用
クラステンプレートの関数としてのパラメータ
クラステンプレートのパイ生成汎用クラス
テンプレートクラスのパイ生成テンプレートクラス
複数クラス、すべての関数がクラスの内部に書き込まれ、演算子がウォーミングアップを再ロードします.
複数クラス、すべての関数がクラスの内部に書かれ、クラステンプレート
【プレゼンテーション】Friend関数を悪用した結果-通常のコード準備
複数クラス、すべての関数がクラスの内部に書かれています(CPP 1つ):問題が投げ出されます
テンプレート関数が友元関数に遭遇した場合、問題は解決されます.
友元関数の乱用の結果
【結論】:友元関数は不要、友元関数は不要
【結論】テンプレート類のcppファイルと.hヘッダファイルを別々に書く場合は、cppファイルも含めます
クラステンプレートにstaticメンバー変数がある場合.
クラステンプレートの実質的な分析から、コンパイラは自動的に私たちのために2つのクラスに書きます.
クラステンプレート配列の例
1主関数:
2ヘッダファイル:MyVector
クラス関数実装ファイルMyVector.cpp
クラステンプレート構造体ケース
クラス関数実装ファイルMyVector.h内容は変わらない
クラス関数実装ファイルMyVector.cpp内容は変わらない
メイン関数を次のように変更します.
main.cpp
ジョブ:
上のプログラムの基礎の上で:
1 Teacherクラスを最適化し、属性はchar*panmeになり、購入関数にメモリを割り当てる
2 Teacherクラスを最適化し、構造関数はpanmeが指すメモリ空間を解放する
3 Teacherクラスを最適化し、浅いコピーの再ロードを避ける=コピー構造関数を書き換える
4 Teacherクラスを最適化し、Teacherで<
5テンプレート配列クラスにint char Teacher Teacher*(ポインタタイプ)を格納
転載先:https://blog.51cto.com/990487026/1825511
【汎用プログラミング】
関数テンプレート
なぜ関数テンプレートがあるのか
現象:
関数のビジネスロジックと同様
関数のパラメータタイプが異なります
【最も一般的】関数テンプレートの明示的な呼び出し
【非常用】タイプ導出
複数のパラメータ、パラメータ定義に使用する必要があります
関数テンプレート、intタイプ配列、char文字列ソートを実現するには:
関数テンプレートと一般関数の本質的な違い
関数テンプレートと一般的な関数を組み合わせた呼び出し型の研究:
C++はどのように関数テンプレートメカニズムをサポートしますか?
関数テンプレートメカニズムの結論
クラステンプレート
クラステンプレートの定義
クラステンプレートの関数としてのパラメータ
クラステンプレートのパイ生成汎用クラス
テンプレートクラスのパイ生成テンプレートクラス
複数クラス、すべての関数がクラスの内部に書き込まれ、演算子がウォーミングアップを再ロードします.
複数クラス、すべての関数がクラスの内部に書かれ、クラステンプレート
【プレゼンテーション】Friend関数を悪用した結果-通常のコード準備
複数クラス、すべての関数がクラスの内部に書かれています(CPP 1つ):問題が投げ出されます
テンプレート関数が友元関数に遭遇した場合、問題は解決されます.
友元関数の乱用の結果
【結論】:友元関数は不要、友元関数は不要
【結論】テンプレート類のcppファイルと.hヘッダファイルを別々に書く場合は、cppファイルも含めます
クラステンプレートにstaticメンバー変数がある場合.クラステンプレートの実質的な分析から、コンパイラは自動的に私たちのために2つのクラスに書きます.
クラステンプレート配列の例
クラステンプレート構造体ケース
ジョブ:
-------------------------------------------------------------------------
【なぜ関数テンプレートがあるのか】
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
using namespace std;
void swap1(int &a,int &b)
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
void swap2(char &a,char &b)
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
int main()
{
int a = 10;
int b = 20;
swap1(a,b);
cout <
現象:
関数のビジネスロジックと同様
関数のパラメータタイプが異なります
【最も一般的】関数テンプレートの明示的な呼び出し
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
using namespace std;
//template // ,
template
void myswap(T &a,T &b)
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
int main()
{
int a = 10;
int b = 20;
cout <(a,b);
cout <(c,d);
cout <
【非常用】タイプ導出
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
using namespace std;
//template // ,
template
void myswap(T &a,T &b)
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
int main()
{
int a = 10;
int b = 20;
cout <
複数のパラメータ、パラメータ定義に使用する必要があります
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
using namespace std;
//template // ,
template
void myswap(T &a,T &b,str s)
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
cout <
関数テンプレート、intタイプ配列、char文字列ソートを実現するには:
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
#include
#include
using namespace std;
template
void select_sort(T1 array[],T2 len)
{
if(array == NULL)
{
return ;
}
for(int i=0;i array[j])
{
min = j ;
}
}
int tmp = array[i];
array[i] = array[min];
array[min]= tmp;
}
}
template
void print_arr(T1 array[],T2 len)
{
if(array == NULL)
{
return ;
}
for(int i=0;i(arr,n);
print_arr(arr,n);
char str[]= "Hello,Linux!";
int m = strlen(str);
select_sort(str,m);
print_arr(str,m);
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
0 1 2 3 4 5 6 7 8 9
! , H L e i l l n o u x
chunli@http://990487026.blog.51cto.com~/c++$
関数テンプレートと一般関数の本質的な違い
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
#include
#include
using namespace std;
//swap C++
template
void my_swap(T &a,T &b)
{
cout <
関数テンプレートと一般的な関数を組み合わせた呼び出し型の研究:
【補足】同じ役割ドメインでは、関数の再ロードが発生します
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
/*
1
2 C++
3 ,
4
*/
#include
#include
#include
using namespace std;
template
T Max(T a,T b) //
{
cout <b?a:b;
}
template
T Max(T a,T b,T c)
{
cout <b?a:b;
}
int main()
{
int a = 1;
int b = 2;
Max(a,b); //C++コンパイラは を する
Max<>(a,b); // のテンプレートの パラメータリストの コンパイラでは、テンプレートのみで できます。
Max(3.5,4.4); //テンプレート を に します。テンプレート はより いマッチングを するためです。
Max(3.5,4.4,6.8);// テンプレートのみが します
Max('A',66); // の は に できます
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
1 2 は の です。
1 2 は2 の テンプレートです。
3.5 4.4 2 テンプレートです
3.5 4.4 は3 の テンプレートです。max を2 び します。
3.5 4.4 2 テンプレートです
4.46.8 は2 テンプレートです
65,666 は の です。
chunli@http://990487026.blog.51cto.com~/c++$
C++はどのように関数テンプレートメカニズムをサポートしますか?
C++:
#include
#include
#include
using namespace std;
//swap C++
template
void my_swap(T &a,T &b)
{
T c = 0;
c = a;
a = b;
b = c;
cout <(a,b);
char c = 'C';
char d = 'D';
my_swap(c,d);
return 0;
}
アセンブリにコンパイル:
.file "main.c"
.lcomm __ZStL8__ioinit,1,1
.def ___main; .scl 2; .type 32; .endef
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB1025:
.cfi_startproc
.cfi_personality 0,___gxx_personality_v0
.cfi_lsda 0,LLSDA1025
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
movl $69, 28(%esp)
movl $20, 24(%esp)
leal 24(%esp), %eax
movl %eax, 4(%esp)
leal 28(%esp), %eax
movl %eax, (%esp)
LEHB0:
call __Z7my_swapIiEvRT_S1_
movb $67, 23(%esp)
movb $68, 22(%esp)
leal 22(%esp), %eax
movl %eax, 4(%esp)
leal 23(%esp), %eax
movl %eax, (%esp)
call __Z7my_swapIcEvRT_S1_
LEHE0:
movl $0, %eax
jmp L5
L4:
movl %eax, (%esp)
LEHB1:
call __Unwind_Resume
LEHE1:
L5:
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1025:
.def ___gxx_personality_v0; .scl 2; .type 32; .endef
.section .gcc_except_table,"w"
LLSDA1025:
.byte 0xff
.byte 0xff
.byte 0x1
.uleb128 LLSDACSE1025-LLSDACSB1025
LLSDACSB1025:
.uleb128 LEHB0-LFB1025
.uleb128 LEHE0-LEHB0
.uleb128 L4-LFB1025
.uleb128 0
.uleb128 LEHB1-LFB1025
.uleb128 LEHE1-LEHB1
.uleb128 0
.uleb128 0
LLSDACSE1025:
.text
.section .rdata,"dr"
LC0:
.ascii " \0"
LC1:
.ascii " \316\322\312\307\272\257\312\375\304\243\260\345\12\0"
.section .text$_Z7my_swapIiEvRT_S1_,"x"
.linkonce discard
.globl __Z7my_swapIiEvRT_S1_
.def __Z7my_swapIiEvRT_S1_; .scl 2; .type 32; .endef
__Z7my_swapIiEvRT_S1_:
LFB1026:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
pushl %ebx
subl $36, %esp
.cfi_offset 3, -12
movl $0, -12(%ebp)
movl 8(%ebp), %eax
movl (%eax), %eax
movl %eax, -12(%ebp)
movl 12(%ebp), %eax
movl (%eax), %edx
movl 8(%ebp), %eax
movl %edx, (%eax)
movl 12(%ebp), %eax
movl -12(%ebp), %edx
movl %edx, (%eax)
movl 12(%ebp), %eax
movl (%eax), %ebx
movl 8(%ebp), %eax
movl (%eax), %eax
movl %eax, (%esp)
movl $__ZSt4cout, %ecx
call __ZNSolsEi
subl $4, %esp
movl $LC0, 4(%esp)
movl %eax, (%esp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl %ebx, (%esp)
movl %eax, %ecx
call __ZNSolsEi
subl $4, %esp
movl $LC1, 4(%esp)
movl %eax, (%esp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl -4(%ebp), %ebx
leave
.cfi_restore 5
.cfi_restore 3
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1026:
.section .text$_Z7my_swapIcEvRT_S1_,"x"
.linkonce discard
.globl __Z7my_swapIcEvRT_S1_
.def __Z7my_swapIcEvRT_S1_; .scl 2; .type 32; .endef
__Z7my_swapIcEvRT_S1_:
LFB1027:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
pushl %ebx
subl $36, %esp
.cfi_offset 3, -12
movb $0, -9(%ebp)
movl 8(%ebp), %eax
movzbl (%eax), %eax
movb %al, -9(%ebp)
movl 12(%ebp), %eax
movzbl (%eax), %edx
movl 8(%ebp), %eax
movb %dl, (%eax)
movl 12(%ebp), %eax
movzbl -9(%ebp), %edx
movb %dl, (%eax)
movl 12(%ebp), %eax
movzbl (%eax), %eax
movsbl %al, %ebx
movl 8(%ebp), %eax
movzbl (%eax), %eax
movsbl %al, %eax
movl %eax, 4(%esp)
movl $__ZSt4cout, (%esp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c
movl $LC0, 4(%esp)
movl %eax, (%esp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl %ebx, 4(%esp)
movl %eax, (%esp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c
movl $LC1, 4(%esp)
movl %eax, (%esp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
addl $36, %esp
popl %ebx
.cfi_restore 3
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1027:
.text
.def ___tcf_0; .scl 3; .type 32; .endef
___tcf_0:
LFB1033:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $8, %esp
movl $__ZStL8__ioinit, %ecx
call __ZNSt8ios_base4InitD1Ev
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1033:
.def __Z41__static_initialization_and_destruction_0ii; .scl 3; .type 32; .endef
__Z41__static_initialization_and_destruction_0ii:
LFB1032:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
cmpl $1, 8(%ebp)
jne L9
cmpl $65535, 12(%ebp)
jne L9
movl $__ZStL8__ioinit, %ecx
call __ZNSt8ios_base4InitC1Ev
movl $___tcf_0, (%esp)
call _atexit
L9:
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1032:
.def __GLOBAL__sub_I_main; .scl 3; .type 32; .endef
__GLOBAL__sub_I_main:
LFB1034:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $65535, 4(%esp)
movl $1, (%esp)
call __Z41__static_initialization_and_destruction_0ii
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1034:
.section .ctors,"w"
.align 4
.long __GLOBAL__sub_I_main
.ident "GCC: (rev2, Built by MinGW-builds project) 4.8.0"
.def __Unwind_Resume; .scl 2; .type 32; .endef
.def __ZNSolsEi; .scl 2; .type 32; .endef
.def __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc; .scl 2; .type 32; .endef
.def __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c; .scl 2; .type 32; .endef
.def __ZNSt8ios_base4InitD1Ev; .scl 2; .type 32; .endef
.def __ZNSt8ios_base4InitC1Ev; .scl 2; .type 32; .endef
.def _atexit; .scl 2; .type 32; .endef
クラステンプレート:
クラステンプレートは、クラスに必要なデータのタイプパラメータ化を実現するために使用されます.
クラステンプレートは配列、テーブル、図などのデータ構造を表す上で特に重要であり、
クラステンプレートの定義
クラス末の使用
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
#include
#include
using namespace std;
template
class A
{
public:
A(T a)
{
this->a = a;
}
void printf()
{
cout <a(11); // ,
a.printf();
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
a= 11
chunli@http://990487026.blog.51cto.com~/c++$
クラステンプレートの関数としてのパラメータ
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
#include
#include
using namespace std;
template
class A
{
public:
A(T a)
{
this->a = a;
}
void printf()
{
cout < &a)// , ,
{
a.printf();
}
int main()
{
A a(11); //
A b(22),c(33);
useA(a); //
useA(b);
useA(c);
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
a= 11
a= 22
a= 33
chunli@http://990487026.blog.51cto.com~/c++$
クラステンプレートのパイ生成汎用クラス
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
#include
#include
using namespace std;
template
class A
{
public:
A(T a)
{
this->a = a;
}
void printf()
{
cout <
{
public:
B(int a,int b):A(a)
{
this->b = b;
}
void printf()
{
cout <
テンプレートクラスのパイ生成テンプレートクラス
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
#include
#include
using namespace std;
template
class A
{
public:
A(T a)
{
this->a = a;
}
void printf()
{
cout <
class C:public A
{
public:
C(T c,T a):A(a)
{
this->c = a;
}
void printf()
{
cout < c1(1,2); c1.printf();
C c2(66,65); c2.printf();
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run main.cpp && ./run
c=2
c=A
chunli@http://990487026.blog.51cto.com~/c++$
複数クラス、すべての関数がクラスの内部に書き込まれ、演算子がウォーミングアップを再ロードします.
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
#include
#include
using namespace std;
class Complex
{
friend ostream& operator<a = a;
this->b = b;
}
void printf()
{
cout <a=" <a <b=" <b <a + c2.a,this->b+c2.b);
return tmp;
}
protected:
int a;
int b;
};
// ,
ostream& operator<
複数クラス、すべての関数がクラスの内部に書かれ、クラステンプレート
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
#include
#include
using namespace std;
/*
<> , ,
*/
template
class Complex
{
// ,
friend ostream& operator< ";
out <a = a;
this->b = b;
}
void printf()
{
cout <a=" <a <b=" <b <a + c2.a,this->b+c2.b);
return tmp;
}
protected:
T a;
T b;
};
/*
ostream& operator< c1(2,4);
Complex c2(3,5);
Complex c3 = c1 +c2; c3.printf();
cout < a=5 b=9
chunli@http://990487026.blog.51cto.com~/c++$
【プレゼンテーション】Friend関数を悪用した結果-通常のコード準備
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
#include
#include
using namespace std;
/*
<> , ,
*/
template
class Complex
{
// ,
friend ostream& operator< ";
out <a = a;
this->b = b;
}
void printf()
{
cout <a=" <a <b=" <b <a + c2.a,this->b+c2.b);
return tmp;
}
protected:
T a;
T b;
};
/*
ostream& operator< c1(2,4);
Complex c2(3,5);
Complex c4 = MySub(c1,c2);
cout < a=-1 b=-1
chunli@http://990487026.blog.51cto.com~/c++$
複数クラス、すべての関数がクラスの内部に書かれています(CPP 1つ):問題が投げ出されます
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
#include
#include
using namespace std;
template
class Complex
{
// ,
friend ostream& operator<
ostream& operator<
//
//
Complex Complex:: operator+(Complex &c2)
{
cout < tmp(this->a + c2.a,this->b+c2.b);
Complex tmp(this->a + c2.a,this->b+c2.b);
return tmp;
}
template
Complex::Complex (T a ,T b)
{
cout <a = a;
this->b = b;
}
template
void Complex::printf()
{
cout < c1(2,4); c1.printf();
Complex c2(3,5);
Complex c3 = c1 + c2;
Complex c4 = MySub(c1,c2);
cout <&)’ declares a non-template function [-Wnon-template-friend]
friend ostream& operator<
テンプレート関数が友元関数に遭遇した場合、問題は解決されます.
chunli@http://990487026.blog.51cto.com~/c++$ cat haha.cpp
#include
using namespace std;
template
class Complex
{
friend std::ostream& operator <(std::ostream& os, const Complex& c);
public:
Complex(T a, T b);
protected:
T a;
T b;
};
template
std::ostream& operator <& c)
{
os <
Complex::Complex(T a, T b)
{
cout <a = a;
this->b = b;
}
int main()
{
Complex c1(2, 4);
cout <ConsoleApplication2.exe
Complex a=2 b=4
a=2 b= 4
Linux GCC :
chunli@http://990487026.blog.51cto.com~/c++$ g++ -g -o run haha.cpp && ./run
haha.cpp: In instantiation of ‘class Complex’:
haha.cpp:33:17: required from here
haha.cpp:7:23: error: template-id ‘operator<’ for ‘std::ostream& operator<&)’ does not match any template declaration
friend std::ostream& operator <(std::ostream& os, const Complex& c);
^
chunli@http://990487026.blog.51cto.com~/c++$
友元関数の乱用の結果
#include
using namespace std;
template
class Complex;
template
Complex MySub(Complex &c1, Complex &c2);
template
class Complex
{
friend std::ostream& operator <(std::ostream& os, const Complex& c);
friend Complex MySub(Complex &c1, Complex &c2);
public:
Complex(T a, T b);
protected:
T a;
T b;
};
template
Complex MySub(Complex &c1, Complex &c2)
{
Complex tmp(c1.a - c2.a, c1.b - c2.b);
return tmp;
}
template
std::ostream& operator <& c)
{
os <
Complex::Complex(T a, T b)
{
cout <a = a;
this->b = b;
}
int main()
{
Complex c1(2, 4);
Complex c2(1, 2);
Complex c3 = MySub(c1,c2);
cout <ConsoleApplication2.exe
Complex a=2 b=4
Complex a=1 b=2
Complex a=1 b=2
a=1 b= 2
【結論】:友元関数は不要、友元関数は不要
【結論】テンプレート類のcppファイルと.hヘッダファイルを別々に書く場合は、cppファイルも含めます
クラステンプレートにstaticメンバー変数がある場合.
クラステンプレートの実質的な分析から、コンパイラは自動的に私たちのために2つのクラスに書きます.
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
#include
using namespace std;
template
class A
{
public:
static T a;
};
template
T A::a = 0;
int main()
{
A a1; a1.a++;
A a2; a2.a++;
A a3; a3.a++;
cout < b1; b1.a += 3.5;
A b2; b2.a += 3.5;
A b3; b3.a += 3.5;
cout <
クラステンプレート配列の例
1主関数:
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
#include "MyVector.cpp"
void main()
{
MyVector myv1(10);
for (int i = 0; i myv2 = myv1;
for (int i = 0; i
2ヘッダファイル:MyVector
#include
using namespace std;
template
class MyVector
{
friend ostream & operator<(ostream &out, const MyVector &obj);
public:
MyVector(int size = 0); //
MyVector(const MyVector &obj); //
~MyVector(); //
public:
T& operator[] (int index);
// a3 = a2 = a1;
MyVector &operator=(const MyVector &obj);
public:
int getLen()
{
return m_len;
}
protected:
T *m_space;
int m_len;
};
クラス関数実装ファイルMyVector.cpp
#include
using namespace std;
#include "MyVector.h"
template
ostream & operator< &obj)
{
for (int i = 0; i myv1(10);
template
MyVector::MyVector(int size) //
{
m_space = new T[size];
m_len = size;
}
//MyVector myv2 = myv1;
template
MyVector::MyVector(const MyVector &obj) //
{
// myv1
m_len = obj.m_len;
m_space = new T[m_len];
//copy
for (int i = 0; i
MyVector::~MyVector() //
{
if (m_space != NULL)
{
delete[] m_space;
m_space = NULL;
m_len = 0;
}
}
template
T& MyVector::operator[] (int index)
{
return m_space[index];
}
// a3 = a2 = a1;
template
MyVector & MyVector::operator=(const MyVector &obj)
{
// a2
if (m_space != NULL)
{
delete[] m_space;
m_space = NULL;
m_len = 0;
}
// a1
m_len = obj.m_len;
m_space = new T[m_len];
//copy
for (int i = 0; i
VS :
C:\Users\chunli\Documents\c_c++\ConsoleApplication2\Debug>ConsoleApplication2.exe
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
hello...
. . .
クラステンプレート構造体ケース
クラス関数実装ファイルMyVector.h内容は変わらない
クラス関数実装ファイルMyVector.cpp内容は変わらない
メイン関数を次のように変更します.
main.cpp
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
#include "MyVector.cpp"
class Teacher
{
public:
Teacher()
{
age = 33;
strcpy(name, "");
}
Teacher(char *name, int age)
{
this->age = age;
strcpy(this->name, name);
}
void printT()
{
cout < tArray(4);
tArray[0] = t1;
tArray[1] = t2;
tArray[2] = t3;
tArray[3] = t4;
for (int i = 0; i<4; i++)
{
Teacher tmp = tArray[i];
tmp.printT();
}
}
VS :
C:\Users\chunli\Documents\c_c++\ConsoleApplication2\Debug>ConsoleApplication2.exe
t1, 31
t2, 32
t3, 33
t4, 34
C:\Users\chunli\Documents\c_c++\ConsoleApplication2\Debug>
ジョブ:
上のプログラムの基礎の上で:
1 Teacherクラスを最適化し、属性はchar*panmeになり、購入関数にメモリを割り当てる
2 Teacherクラスを最適化し、構造関数はpanmeが指すメモリ空間を解放する
3 Teacherクラスを最適化し、浅いコピーの再ロードを避ける=コピー構造関数を書き換える
4 Teacherクラスを最適化し、Teacherで<
5テンプレート配列クラスにint char Teacher Teacher*(ポインタタイプ)を格納
転載先:https://blog.51cto.com/990487026/1825511