C++向上1【汎用プログラミング】関数テンプレート類テンプレート

22774 ワード

【転載お断り】
【汎用プログラミング】
関数テンプレート
なぜ関数テンプレートがあるのか
現象:
関数のビジネスロジックと同様
関数のパラメータタイプが異なります
【最も一般的】関数テンプレートの明示的な呼び出し
【非常用】タイプ導出
複数のパラメータ、パラメータ定義に使用する必要があります
関数テンプレート、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