Suy ra kiểu trả về của hàm mẫu. Mẫu

10.1. Xác định mẫu hàm

Đôi khi có vẻ như một ngôn ngữ được gõ mạnh sẽ tạo ra rào cản cho việc thực hiện các chức năng rất đơn giản. Ví dụ: mặc dù thuật toán sau cho hàm min() là tầm thường, nhưng việc gõ mạnh yêu cầu các biến thể của nó phải được triển khai cho tất cả các loại mà chúng ta sẽ so sánh:

int phút(int a, int b) (

trả lại a b ? một: b;

nhân đôi phút(nhân đôi a, nhân đôi b) (

trả lại a b ? một: b;

Một cách thay thế hấp dẫn để xác định rõ ràng từng phiên bản của hàm min() là sử dụng macro có thể mở rộng tiền xử lý:

#define min(a, b) ((a) (b) ? (a) : (b))

Nhưng cách tiếp cận này tiềm ẩn nhiều nguy hiểm. Macro được xác định ở trên hoạt động chính xác với các lệnh gọi đơn giản tới min(), ví dụ:

phút(10.0, 20.0);

nhưng nó có thể mang lại những điều bất ngờ trong những trường hợp phức tạp hơn: cơ chế như vậy không hoạt động giống như một lệnh gọi hàm, nó chỉ thực hiện thay thế đối số văn bản. Kết quả là giá trị của cả hai đối số được đánh giá hai lần: một lần khi so sánh a và b và một lần khi tính toán kết quả được macro trả về:

#include iostream

#define min(a,b) ((a) (b) ? (a) : (b))

const kích thước int = 10;

trong khi (min(p++,ia) != ia)

cout "elem_cnt: "elem_cnt

" đang mong đợi: " size endl;

Thoạt nhìn, chương trình này đếm số phần tử trong một mảng số nguyên. Nhưng trong trường hợp này, macro min() mở rộng không chính xác vì thao tác tăng sau được áp dụng cho đối số con trỏ hai lần cho mỗi lần thay thế. Kết quả là chương trình in ra một dòng biểu thị phép tính sai:

elem_cnt: 5 mong đợi: 10

Các mẫu hàm cung cấp một cơ chế mà qua đó chúng ta có thể bảo toàn ngữ nghĩa của các định nghĩa và lệnh gọi hàm (đóng gói một đoạn mã ở một nơi trong chương trình và đảm bảo rằng các đối số được đánh giá một lần) mà không phải hy sinh kiểu gõ mạnh của ngôn ngữ C++, chẳng hạn như trường hợp với macro.

Mẫu đưa ra một thuật toán được sử dụng để tự động tạo ra các phiên bản hàm với các loại khác nhau. Lập trình viên tham số hóa tất cả hoặc chỉ một số loại trong giao diện của hàm (nghĩa là các loại tham số chính thức và giá trị trả về), giữ nguyên phần thân của nó. Một hàm rất phù hợp để làm mẫu nếu việc triển khai nó vẫn bất biến trên một tập hợp các phiên bản nhất định khác nhau về kiểu dữ liệu, chẳng hạn như trong trường hợp min().

Đây là cách định nghĩa mẫu hàm min():

Loại lớp mẫu

Nhập min2(Loại a, Loại b) (

trả lại a b ? một: b;

// đúng: min(int, int);

// đúng: min(double, double);

phút(10.0, 20.0);

Nếu thay vì macro tiền xử lý min(), chúng ta thay thế mẫu này vào văn bản của chương trình trước đó thì kết quả sẽ đúng:

elem_cnt: 10 mong đợi: 10

(Thư viện chuẩn C++ có các mẫu hàm cho nhiều thuật toán thường được sử dụng, chẳng hạn như min(). Các thuật toán này được mô tả trong Chương 12. Và trong chương giới thiệu này, chúng tôi cung cấp các phiên bản đơn giản hóa của riêng mình về một số thuật toán trong Thư viện chuẩn. )

Cả phần khai báo và định nghĩa của mẫu hàm phải luôn bắt đầu bằng mẫu từ khóa, theo sau là danh sách các mã định danh được phân tách bằng dấu phẩy, được đặt trong dấu ngoặc nhọn " và " - danh sách các tham số mẫu, không được để trống. Một mẫu có thể có các tham số loại, đại diện cho một loại và các tham số hằng, đại diện cho một biểu thức hằng cố định.

Tham số loại bao gồm từ khóa lớp hoặc từ khóa tên kiểu theo sau là mã định danh. Những từ này luôn chỉ ra rằng tên sau đây đề cập đến loại tích hợp sẵn hoặc do người dùng xác định. Tên của tham số mẫu do người lập trình chọn. Trong ví dụ trên, chúng tôi đã sử dụng tên Loại, nhưng chúng tôi có thể chọn bất kỳ tên nào khác:

lớp mẫu Glorp

Glorp min2(Glorp a, Glorp b) (

trả lại a b ? một: b;

Khi khởi tạo (tạo một phiên bản cụ thể) một mẫu, loại tích hợp thực tế hoặc do người dùng xác định sẽ được thay thế cho tham số loại. Bất kỳ loại int, double, char*, vectorint hoặc listdouble đều là đối số mẫu hợp lệ.

Một tham số không đổi trông giống như một khai báo thông thường. Nó nói rằng thay vì tên tham số, nên thay thế giá trị không đổi từ định nghĩa mẫu. Ví dụ: size là một tham số không đổi biểu thị kích thước của mảng mảng:

Loại lớp mẫu, kích thước int

Nhập min(Loại (arr) );

Sau danh sách tham số mẫu là phần khai báo hoặc định nghĩa hàm. Nếu bạn không chú ý đến sự hiện diện của các tham số ở dạng bộ xác định kiểu hoặc hằng, thì định nghĩa của mẫu hàm trông giống hệt như đối với các hàm thông thường:

Loại lớp mẫu, kích thước int

/* Hàm tham số hóa để tìm kiếm

*giá trị nhỏ nhất trong mảng */

Nhập min_val = r_array;

cho (int i = 1; kích thước i; ++i)

nếu (r_array[i] min_val)

min_val = r_array[i];

Trong ví dụ này, Loại xác định loại giá trị được trả về bởi hàm min(), loại tham số r_array và loại biến cục bộ min_val; size chỉ định kích thước của mảng r_array. Trong quá trình vận hành chương trình, khi sử dụng hàm min(), mọi loại tích hợp và do người dùng xác định đều có thể được thay thế cho Loại và một số biểu thức hằng số nhất định có thể được thay thế cho kích thước. (Hãy nhớ rằng bạn có thể làm việc với một hàm theo hai cách: gọi nó hoặc lấy địa chỉ của nó).

Quá trình thay thế các loại và giá trị cho các tham số được gọi là khởi tạo mẫu. (Chúng ta sẽ đi vào chi tiết hơn về điều này trong phần tiếp theo.)

Danh sách các tham số cho hàm min() của chúng ta có vẻ rất ngắn. Như đã thảo luận trong Phần 7.3, khi tham số là một mảng, một con trỏ tới phần tử đầu tiên của nó sẽ được truyền, nhưng chiều thứ nhất của đối số mảng thực tế trong định nghĩa hàm không xác định được. Để giải quyết khó khăn này, chúng tôi đã khai báo tham số đầu tiên là min() làm tham chiếu đến mảng và tham số thứ hai là kích thước của mảng. Nhược điểm của phương pháp này là khi sử dụng một mẫu có các mảng cùng kiểu int nhưng có kích thước khác nhau, các phiên bản khác nhau của hàm min() sẽ được tạo ra (hoặc được khởi tạo).

Tên tham số được phép sử dụng trong khai báo hoặc định nghĩa mẫu. Tham số loại đóng vai trò là công cụ xác định loại; nó có thể được sử dụng theo cách tương tự như bất kỳ công cụ xác định kiểu tích hợp hoặc do người dùng xác định nào, ví dụ như trong các khai báo biến hoặc các thao tác truyền kiểu. Tham số hằng số được sử dụng làm giá trị không đổi - trong đó cần có biểu thức hằng số, ví dụ: để chỉ định kích thước trong khai báo mảng hoặc làm giá trị ban đầu của phần tử liệt kê.

// size xác định kích thước của tham số mảng và khởi tạo

// biến kiểu const int

Loại lớp mẫu, kích thước int

Nhập min(const Loại (r_array))

const int loc_size = kích thước;

Nhập loc_array;

Nếu một đối tượng, hàm hoặc loại có cùng tên với tham số mẫu được khai báo trong phạm vi toàn cục thì tên toàn cục sẽ bị ẩn. Trong ví dụ sau, loại của biến tmp không phải là double mà giống với tham số mẫu Loại:

typedef loại kép;

Loại lớp mẫu

Loại min(Loại a, Loại b)

// tmp có cùng loại với loại tham số mẫu, không phải loại đã cho

// typedef toàn cục

Gõ tm = a b ? một: b;

Một đối tượng hoặc kiểu được khai báo bên trong định nghĩa mẫu hàm không được có cùng tên với bất kỳ tham số nào:

Loại lớp mẫu

Loại min(Loại a, Loại b)

// lỗi: khai báo lặp lại tên Loại khớp với tên

// tham số mẫu

typedef loại kép;

Gõ tmp = a b ? một: b;

Tên của tham số loại mẫu có thể được sử dụng để chỉ định loại trả về:

// đúng: T1 đại diện cho kiểu giá trị được trả về bởi min(),

// và T2, T3 là tham số kiểu của hàm này

mẫu lớp T1, lớp T2, lớp T3

Trong một danh sách tham số, một tên nhất định chỉ được phép sử dụng một lần. Ví dụ: định nghĩa sau sẽ bị gắn cờ là lỗi biên dịch:

// lỗi: sử dụng lại tên tham số Loại không chính xác

Loại lớp mẫu, Loại lớp

Loại min(Loại, Loại);

Tuy nhiên, cùng một tên có thể được sử dụng nhiều lần trong một khai báo hoặc định nghĩa mẫu:

// đúng: sử dụng lại tên Loại bên trong mẫu

Loại lớp mẫu

Loại min(Loại, Loại);

Loại lớp mẫu

Loại tối đa(Loại, Loại);

Tên tham số trong khai báo và định nghĩa không nhất thiết phải khớp nhau. Do đó, cả ba khai báo min() đều tham chiếu đến cùng một mẫu hàm:

// cả ba khai báo min() đều tham chiếu đến cùng một mẫu hàm

// chuyển tiếp các khai báo mẫu

lớp mẫu T T min(T, T);

lớp mẫu U U min(U, U);

// định nghĩa mẫu thực tế

Loại lớp mẫu

Nhập min(Loại a, Loại b) ( /* ... */ )

Số lần cùng một tham số mẫu xuất hiện trong danh sách tham số hàm là không giới hạn. Ví dụ sau sử dụng Type để biểu thị hai tham số khác nhau:

// đúng: Kiểu được sử dụng lặp đi lặp lại trong danh sách tham số mẫu

Loại lớp mẫu

Gõ sum(const vectorType , Type);

Nếu một mẫu hàm có một số tham số kiểu thì mỗi tham số đó phải được đặt trước từ khóa lớp hoặc tên kiểu:

// đúng: tên kiểu và từ khóa lớp có thể được xen kẽ

tên kiểu mẫu T, lớp U

// lỗi: phải là tên kiểu T, lớp U hoặc

// tên kiểu chữ T, tên kiểu chữ U

tên kiểu mẫu T, U

Trong danh sách tham số của mẫu hàm, từ khóa typename và class có cùng ý nghĩa và do đó có thể thay thế cho nhau. Một trong hai cách này có thể được sử dụng để khai báo các tham số loại mẫu khác nhau trong cùng một danh sách (như được minh họa bằng mẫu hàm trừ()). Để biểu thị một tham số loại, thoạt nhìn, sẽ tự nhiên hơn khi sử dụng từ khóa typename thay vì class, bởi vì nó chỉ rõ rằng nó được theo sau bởi một tên loại. Tuy nhiên, từ này chỉ mới được thêm vào ngôn ngữ gần đây như một phần của tiêu chuẩn C++, vì vậy bạn có thể sẽ thấy lớp từ này trong các chương trình cũ hơn. (Chưa kể rằng lớp đó ngắn hơn tên chữ và bản chất con người là lười biếng.)

Từ khóa typename giúp phân tích các định nghĩa mẫu dễ dàng hơn. (Chúng tôi sẽ chỉ giải thích ngắn gọn lý do tại sao nó lại cần thiết. Đối với những ai muốn tìm hiểu thêm về điều này, chúng tôi khuyên bạn nên tham khảo cuốn sách “Thiết kế và phát triển C++” của Stroustrup.)

Khi phân tích cú pháp theo cách này, trình biên dịch phải phân biệt các biểu thức có kiểu với các biểu thức không phải kiểu; không phải lúc nào cũng có thể xác định được điều này. Ví dụ: nếu trình biên dịch gặp biểu thức Parm::name trong định nghĩa mẫu và nếu Parm là tham số kiểu đại diện cho một lớp, thì tên có nên được coi là đại diện cho một thành viên kiểu của lớp Parm không?

lớp mẫu Parm, lớp U

Parm::tên * p; // đây là khai báo con trỏ hay phép nhân?

// Thực chất là phép nhân

Trình biên dịch không biết liệu tên có phải là một loại hay không vì định nghĩa của lớp được đại diện bởi Parm không có sẵn cho đến khi mẫu được khởi tạo. Để phân tích cú pháp định nghĩa mẫu như vậy, người dùng phải cho trình biên dịch biết biểu thức nào bao gồm các loại. Điều này được thực hiện bằng cách sử dụng từ khóa typename. Ví dụ: nếu chúng ta muốn biểu thức Parm::name trong mẫu hàmtrừ() là tên của một loại và do đó toàn bộ dòng được coi là một khai báo con trỏ, thì chúng ta cần sửa đổi văn bản như sau:

lớp mẫu Parm, lớp U

Parm trừ(Mảng Parm*, giá trị U)

tên kiểu Parm::name * p; // bây giờ đây là một khai báo con trỏ

Từ khóa tên kiểu cũng được sử dụng trong danh sách tham số mẫu để chỉ ra rằng tham số đó là một kiểu.

Mẫu hàm có thể được khai báo là nội tuyến hoặc bên ngoài, giống như một hàm thông thường. Bộ xác định được đặt sau danh sách tham số, không phải trước mẫu từ.

// đúng: chỉ định sau danh sách tham số

tên kiểu chữ mẫu Loại

Loại min(Loại, Loại);

// lỗi: bộ xác định nội tuyến không đúng chỗ

tên kiểu chữ mẫu Loại

Nhập min(ArrayType, int);

Bài tập 10.1

Xác định định nghĩa mẫu hàm nào trong số này là không chính xác. Sửa chữa những sai lầm.

(a) mẫu lớp T, U, lớp V

void foo(T, U, V);

(b) lớp mẫu T

(c) lớp mẫu T1, tên kiểu chữ T2, lớp T3

(d) tên kiểu mẫu nội tuyến T

T foo(T, unsigned int*);

(e) lớp mẫu myT, lớp myT

void foo(myT, myT);

(f) lớp mẫu T

(g) typedef char Ctype;

Loại lớp mẫu

Ctype foo(Ctype a, Ctype b);

Bài tập 10.2

Những khai báo mẫu lặp lại nào là sai? Tại sao?

(a) Loại lớp mẫu

Thanh gõ(Loại, Loại);

Loại lớp mẫu

Thanh gõ(Loại, Loại);

(b) lớp mẫu T1, lớp T2

thanh trống(T1, T2);

tên kiểu mẫu C1, tên kiểu C2

thanh trống (C1, C2);

Bài tập 10.3

Viết lại hàm putValues() từ Phần 7.3.3 làm mẫu. Tham số hóa nó để có hai tham số mẫu (đối với loại phần tử mảng và kích thước của mảng) và một tham số hàm là tham chiếu đến mảng. Viết định nghĩa của mẫu hàm.

Từ cuốn sách Microsoft Office tác giả Leontyev Vitaly Petrovich

Chọn mẫu Như chúng tôi đã nói, Nhà xuất bản được thiết kế để hoạt động ở chế độ “từng bước” - như trước đây, chúng tôi đang tập hợp từng phần xuất bản trong tương lai. Và chính xác hơn nữa, chúng tôi tạo ra nó dựa trên một trong vô số mẫu. Hơn một nghìn rưỡi mẫu được lưu trữ trên CD Nhà xuất bản

Từ cuốn sách Hướng dẫn tham khảo C++ tác giả Strousttrap Bjarne

R.7.1.4 Đặc tả mẫu loại Một đặc tả mẫu loại được sử dụng để chỉ định một họ loại hoặc chức năng (xem

Từ cuốn sách Công việc văn phòng hiệu quả tác giả Ptashinsky Vladimir Sergeevich

Khái niệm về mẫu Để đơn giản hóa công việc tạo và định dạng văn bản, tiêu chuẩn hóa việc sắp xếp và thiết kế văn bản, đồ họa, điển hình hóa các hoạt động xử lý tài liệu và những thứ khác, các mẫu tài liệu được sử dụng. Gói Microsoft Office đưa ra các định nghĩa khác nhau về mẫu

Từ cuốn sách Xử lý cơ sở dữ liệu trong Visual Basic®.NET tác giả McManus Geoffrey P

Từ cuốn sách Tạo mẫu Joomla tác giả tác giả không rõ

Cấu trúc thư mục mẫu Bây giờ chúng ta cần quan tâm đến một số điều kiện. Như đã đề cập, mẫu phải có cấu trúc thư mục nhất định: [PathToJoomla!]/templates/[TemplateName]/[PathtoJoomla!]/templates/[TemplateName]/css/[PathtoJoomla!]/templates/[

Từ cuốn sách XSLT tác giả Holzner Stephen

Cấu trúc mẫu Ngoài một tiêu đề đặc biệt, một mẫu cần có cấu trúc. Bạn có thể tạo cấu trúc bằng bảng hoặc thẻ

. Tiếp theo chúng tôi mô tả việc tạo một phiên bản dạng bảng của cấu trúc. Nếu bạn vẫn bật chế độ Bố cục trong Dremweaver, hãy đóng

Từ cuốn sách Công nghệ XSLT tác giả Valikov Alexey Nikolaevich

Tạo một Mẫu Trong Chương 2, tôi đã tạo một mẫu cơ bản để chọn các nút trong Planet.xml và chuyển đổi tài liệu đó sang HTML. Các mẫu trong biểu định kiểu được tạo bằng các phần tử , xác định các quy tắc cho các phép biến đổi cần thiết. Chúng tôi đã tạo một mẫu tìm thấy gốc

Từ cuốn sách Ngôn ngữ lập trình C cho máy tính cá nhân tác giả Bochkov S. O.

Nội dung mẫu Trong thực tế, phần tử xsl:template xác định quy tắc mẫu không chỉ định gì khác ngoài các điều kiện mà quy tắc đó sẽ được thực thi. Các hành động và hướng dẫn cụ thể phải được thực thi được xác định bởi nội dung của phần tử xsl:template và cấu thành

Từ cuốn sách Ngôn ngữ C - Hướng dẫn cho người mới bắt đầu bởi Prata Steven

Định nghĩa hàm Một định nghĩa hàm xác định tên, các tham số hình thức và nội dung của hàm. Nó cũng có thể chỉ định kiểu trả về và lớp lưu trữ của hàm. Cú pháp để xác định hàm là:[<спецификация КП>][<спецификация

Từ cuốn sách Các tính năng không có giấy tờ và ít được biết đến của Windows XP tác giả Klimenko Roman Alexandrovich

Định nghĩa một hàm với một đối số: Các đối số hình thức Định nghĩa hàm của chúng ta bắt đầu bằng hai dòng: space(number)int number; Dòng đầu tiên thông báo cho trình biên dịch rằng hàm space() có một đối số và tên của nó là số. Dòng thứ hai là mô tả cho biết

Từ cuốn sách Cách tạo trang web của riêng bạn và kiếm tiền từ nó. Hướng dẫn thực tế cho người mới bắt đầu kiếm tiền trực tuyến tác giả Mukhutdinov Evgeniy

Tạo mẫu bảo mật Để tạo mẫu bảo mật dựa trên bất kỳ mẫu nào khác, hãy chọn lệnh Lưu dưới dạng từ menu ngữ cảnh của mẫu. Bảng điều khiển quản lý Microsoft sau đó sẽ nhắc bạn cung cấp tên cho mẫu mới, sau đó nó sẽ xuất hiện trong

Từ cuốn sách C++ dành cho người mới bắt đầu bởi Lippman Stanley

Từ cuốn sách của tác giả

10.2. Chỉ định một mẫu hàm Một mẫu hàm mô tả cách xây dựng các hàm cụ thể khi được cung cấp nhiều loại hoặc giá trị thực tế. Quá trình thiết kế được gọi là khởi tạo mẫu. Nó được thực hiện ngầm, như một tác dụng phụ của lệnh gọi

Từ cuốn sách của tác giả

Từ cuốn sách của tác giả

10.11. Ví dụ về mẫu hàm Phần này cung cấp một ví dụ cho thấy cách có thể xác định và sử dụng các mẫu hàm. Điều này xác định mẫu sắp xếp(), sau đó được sử dụng để sắp xếp các phần tử của mảng. Bản thân mảng được biểu diễn bằng mẫu lớp Array (xem

Từ cuốn sách của tác giả

16.1. Định nghĩa một mẫu lớp Giả sử chúng ta cần định nghĩa một lớp hỗ trợ cơ chế xếp hàng. Hàng đợi là cấu trúc dữ liệu để lưu trữ một tập hợp các đối tượng; chúng được đặt ở cuối hàng đợi và được lấy lại từ đầu. Hành vi của hàng đợi được mô tả

Bạn có thể tạo nguyên mẫu cho một mẫu hàm bằng cách khai báo trước nó. Tuyên bố này thông báo cho trình biên dịch về sự hiện diện của mẫu và cũng thông báo cho trình biên dịch về các tham số dự kiến. Ví dụ: nguyên mẫu mẫu hàm Sắp xếp sẽ trông như thế này:

bản mẫu void Sort(T mảng, kích thước Tsize);

Tên của các tham số chính thức của mẫu có thể không giống nhau trong phần khai báo và định nghĩa trước mẫu. Vì vậy, ví dụ: trong đoạn mã sau, cả nguyên mẫu mẫu và định nghĩa mẫu đều đề cập đến cùng một hàm:

bản mẫu T tối đa(T, T);

bản mẫu

Loại tối đa(Loại a, Loại b)

nếu (a > b) trả về a; ngược lại trả về b;

Sử dụng mẫu hàm

Mẫu hàm mô tả cách xây dựng một hàm cụ thể dựa trên một hoặc nhiều loại thực tế. Trình biên dịch tự động tạo đại diện nội dung hàm cho các loại được chỉ định trong lệnh gọi. Quá trình này được gọi là sự chỉ rõ. Nó xảy ra khi một hàm mẫu được gọi.

Ví dụ, trong ví dụ sau, hàm min() được khởi tạo hai lần: một lần với kiểu int và một lần với kiểu double:

bản mẫu

Loại min(Loại a, Loại b)

nếu một< b) return a; else return b;

int x = 4, y = 5, z;

gấp đôi t = 6,56, r = 3,07, p;

Chuyên môn mẫu chức năng

Hàm mẫu chuyên dụng là hàm thông thường có tên giống với hàm trong mẫu nhưng được xác định cho các tham số thuộc loại cụ thể. Các hàm mẫu chuyên biệt được xác định khi một mẫu chung không phù hợp với một loại dữ liệu cụ thể. Ví dụ: hàm mẫu min

bản mẫu

Loại min(Loại a, Loại b)

nếu một< b) return a; else return b;

không thể được sử dụng cho các chuỗi (đối với loại char*), vì mã do trình biên dịch tạo ra sẽ chỉ so sánh các vị trí bộ nhớ (địa chỉ) của chúng. Để so sánh chính xác các chuỗi, bạn có thể xác định một hàm chuyên biệt:

char* phút(char* s1, char* s2)

if (strcmp(s1,s2)>0) return s2; nếu không thì trả về s1;

Sau đó, bạn có thể truy cập một hàm như vậy theo cách tương tự như hàm mẫu:

int i1 = 3, i2 = 5;

cout<< “max int = ” << max(i1, i2) << endl;

char* s1 = “Đại bàng vàng”;

char* s2 = “Chim ưng Perigrine”;

cout<< “max str = “ << max(s1, s2) << endl;

Mẫu lớp học

Mẫu lớpđưa ra định nghĩa chung về một họ các lớp sử dụng các kiểu hoặc hằng số tùy ý. Mẫu xác định thành viên dữ liệu mẫuhàm thành viên mẫu. Khi một mẫu lớp đã được xác định, bạn có thể hướng dẫn trình biên dịch tạo một lớp mới dựa trên nó cho một kiểu hoặc hằng số cụ thể.

Cú pháp mẫu lớp

bản mẫu<<список аргументов шаблона>>

lớp học<имя класса>

<тело класса>

Từ khóa mẫu được theo sau bởi một hoặc nhiều đối số (tham số) được đặt trong dấu ngoặc nhọn và được phân tách bằng dấu phẩy. Mỗi đối số có thể là một từ khóa lớp, theo sau là một mã định danh cho biết loại được tham số hóa. Danh sách đối số mẫu không được để trống.

Tiếp theo là định nghĩa lớp. Nó tương tự như định nghĩa lớp thông thường, ngoại trừ việc nó sử dụng danh sách đối số mẫu.

Các tham số mẫu bao gồm từ khóa lớp theo sau là mã định danh thường được gọi là thông số loại. Nói cách khác, chúng thông báo cho trình biên dịch rằng mẫu mong đợi một kiểu làm đối số.

Trước đây chúng tôi đã coi một công cụ như vậy là các mẫu trong C++ khi chúng tôi tạo các tệp . Tại sao bạn nên sử dụng các mẫu đã được viết trong bài viết với các mẫu chức năng. Ở đó chúng ta đã xem xét các quy định cơ bản của các mẫu trong C++. Chúng ta hãy nhớ đến họ.

Bất kỳ mẫu nào cũng bắt đầu bằng mẫu từ, có thể là mẫu hàm hoặc mẫu lớp. Từ khóa mẫu được theo sau bởi dấu ngoặc nhọn -< >, liệt kê danh sách các tham số mẫu. Mỗi tham số phải được đặt trước bởi lớp từ hoặc tên kiểu dành riêng. Việc thiếu các từ khóa này sẽ được trình biên dịch hiểu là . Một số ví dụ về khai báo mẫu:

Bản mẫu

Bản mẫu

Bản mẫu

Từ khóa typename cho trình biên dịch biết rằng mẫu sẽ sử dụng kiểu dữ liệu có sẵn như: int, double, float, char, v.v. Và từ khóa class cho trình biên dịch biết rằng mẫu hàm sẽ sử dụng các kiểu dữ liệu tùy chỉnh làm tham số, tức là các lớp học. Nhưng trong mọi trường hợp không được nhầm lẫn tham số mẫu với mẫu lớp. Nếu chúng ta cần tạo một mẫu lớp với một tham số kiểu int và char , thì mẫu lớp sẽ trông như thế này:

Bản mẫu

trong đó T là tham số mẫu lớp có thể chấp nhận bất kỳ kiểu dữ liệu tích hợp nào, đó là thứ chúng ta cần.

Và nếu tham số mẫu lớp phải thuộc loại tùy chỉnh, chẳng hạn như Array , trong đó Array là lớp mô tả một mảng, thì mẫu lớp sẽ trông như thế này:

Bản mẫu Tên lớp ( //thân mẫu lớp );

Tốt hơn hết bạn nên tìm hiểu điều này ngay từ đầu để không phát sinh lỗi sau này, ngay cả khi mẫu lớp được viết chính xác.

Hãy tạo một mẫu lớp Stack, trong đó , lưu trữ các phần tử dữ liệu tương tự. Bạn có thể đẩy và đưa dữ liệu vào ngăn xếp. Phần tử được thêm vào ngăn xếp sẽ được đặt ở đầu ngăn xếp. Các phần tử của ngăn xếp được loại bỏ bắt đầu từ trên cùng. Trong mẫu lớp Stack, bạn cần tạo các phương thức chính:

  • — thêm một phần tử vào ngăn xếp;
  • Nhạc pop- Loại bỏ một phần tử khỏi ngăn xếp
  • inStack- hiển thị ngăn xếp trên màn hình;

Vì vậy, hãy triển khai ba phương thức này và cuối cùng chúng ta sẽ có được lớp đơn giản nhất thực hiện hoạt động của cấu trúc ngăn xếp. Đừng quên các hàm tạo và hàm hủy. Xem mã bên dưới.

#include "stdafx.h" #include bản mẫu << "Заталкиваем элементы в стек: "; int ct = 0; while (ct++ != 5) { int temp; cin >> << "\nУдаляем два элемента из стека:\n"; myStack.pop(); // удаляем элемент из стека myStack.pop(); // удаляем элемент из стека myStack.printStack(); // вывод стека на экран return 0; } // конструктор template Cây rơm ::Stack(int s) ( size = s > Cây rơm ngăn xếp bool ngăn xếp bool ngăn xếp trống ::printStack() ( for (int ix = size -1; ix >= 0; ix--) cout<< "|" << setw(4) << stackPtr << endl; }

// mã Code::Khối

// Mã Dev-C++

#bao gồm sử dụng không gian tên std; #bao gồm bản mẫu class Stack ( private: T *stackPtr; // con trỏ tới ngăn xếp int size; // kích thước ngăn xếp T top; // đỉnh của ngăn xếp public: Stack(int = 10); // kích thước ngăn xếp mặc định là 10 phần tử ~Stack () ; // hàm hủy bool push(const T); // đẩy một phần tử vào ngăn xếp bool pop(); // xóa một phần tử khỏi ngăn xếp void printStack(); ); int main() ( Ngăn xếp myStack(5); // điền vào ngăn xếp cout<< "Заталкиваем элементы в стек: "; int ct = 0; while (ct++ != 5) { int temp; cin >> nhiệt độ; myStack.push(temp); ) myStack.printStack(); // in ngăn xếp ra màn hình c<< "\nУдаляем два элемента из стека:\n"; myStack.pop(); // удаляем элемент из стека myStack.pop(); // удаляем элемент из стека myStack.printStack(); // вывод стека на экран return 0; } // конструктор template Cây rơm ::Stack(int s) ( size = s > 0 ? s: 10; // khởi tạo kích thước ngăn xếp stackPtr = new T; // cấp phát bộ nhớ cho ngăn xếp top = -1; // giá trị -1 chỉ ra rằng ngăn xếp trống ) // hàm hủy mẫu Cây rơm ::~Stack() ( delete stackPtr; // xóa ngăn xếp ) // phần tử là một hàm của lớp Stack để đặt một phần tử vào ngăn xếp // giá trị trả về là đúng, thao tác hoàn thành thành công // sai, phần tử chưa được thêm vào mẫu ngăn xếp ngăn xếp bool ::push(const T value) ( ​​if (top == size - 1) return false; // ngăn xếp đầy top++; stackPtr = value; // đẩy phần tử vào ngăn xếp return true; // hoàn thành thành công của thao tác ) // hàm phần tử Lớp ngăn xếp để xóa một phần tử khỏi ngăn xếp // giá trị trả về là đúng, thao tác hoàn thành thành công // sai, ngăn xếp là mẫu trống ngăn xếp bool ::pop() ( if (top == - 1) return false; // ngăn xếp trống stackPtr = 0; // xóa một phần tử khỏi ngăn xếp top--; return true; // hoàn thành thành công thao tác ) // hiển thị ngăn xếp trên mẫu màn hình ngăn xếp trống ::printStack() ( for (int ix = size -1; ix >= 0; ix--) cout<< "|" << setw(4) << stackPtr << endl; }

Như bạn có thể thấy, mẫu lớp Stack được khai báo và định nghĩa trong tệp có hàm main. Tất nhiên, phương pháp tái chế mẫu này không tốt, nhưng nó sẽ có tác dụng làm ví dụ. Dòng 7 - 20 khai báo giao diện mẫu lớp. Việc khai báo lớp được thực hiện theo cách thông thường và trước lớp có một khai báo mẫu, ở dòng 7. Khi khai báo một mẫu lớp, luôn sử dụng cú pháp này.

Dòng 47 - 100 chứa phần tử hàm template của lớp Stack, trước mỗi hàm cần khai báo một template, giống hệt như trước lớp - template . Nghĩa là, hóa ra phần tử hàm của một mẫu lớp được khai báo giống hệt như các mẫu hàm thông thường. Nếu chúng ta mô tả việc triển khai các phương thức bên trong một lớp thì tiêu đề mẫu sẽ là template Không cần phải đăng ký cho từng chức năng.

Để liên kết từng thành phần hàm với một mẫu lớp, như thường lệ, chúng ta sử dụng thao tác phân giải phạm vi nhị phân - :: với tên của mẫu lớp . Đó là những gì chúng ta đã làm ở các dòng 49, 58, 68, 83, 96.

Lưu ý khai báo đối tượng myStack của mẫu lớp Stack trong hàm chính, dòng 24. Dấu ngoặc nhọn phải chỉ rõ ràng loại dữ liệu được sử dụng, điều này không cần thiết trong các mẫu hàm. Tiếp theo, main chạy một số hàm minh họa cách hoạt động của mẫu lớp Stack. Kết quả của chương trình được hiển thị dưới đây.

Chúng ta đẩy các phần tử vào ngăn xếp: 12 3456 768 5 4564 |4564 | 5 | 768 |3456 | 12 Xóa hai phần tử khỏi ngăn xếp: | 0 | 0 | 768 |3456 | 12

Nói cách khác, các mẫu hàm là các hướng dẫn theo phiên bản cục bộ nào của hàm tạo khuôn mẫu được tạo cho một tập hợp tham số và kiểu dữ liệu cụ thể.

Trên thực tế, các mẫu hàm là một công cụ mạnh mẽ trong C++ giúp công việc của lập trình viên trở nên dễ dàng hơn nhiều. Ví dụ: chúng ta cần lập trình một hàm hiển thị các phần tử của một mảng. Nhiệm vụ không khó! Nhưng để viết được hàm như vậy chúng ta phải biết kiểu dữ liệu của mảng mà chúng ta sẽ hiển thị trên màn hình. Và sau đó họ nói với chúng tôi - có nhiều hơn một kiểu dữ liệu, chúng tôi muốn hàm xuất ra các mảng kiểu int, double, float và char.

Hóa ra, nhiệm vụ trở nên phức tạp hơn. Và bây giờ chúng tôi hiểu rằng chúng tôi cần lập trình tối đa 4 chức năng thực hiện các hành động giống nhau nhưng cho các loại dữ liệu khác nhau. Vì chúng ta chưa quen với các mẫu hàm nên chúng ta sẽ làm điều này: chúng ta sẽ sử dụng các tệp .

// nạp chồng hàm printArray để hiển thị mảng trên màn hình void printArray(const int * array, int count) ( for (int ix = 0; ix< count; ix++) cout << array << " "; cout << endl; } void printArray(const double * array, int count) { for (int ix = 0; ix < count; ix++) cout << array << " "; cout << endl; } void printArray(const float * array, int count) { for (int ix = 0; ix < count; ix++) cout << array << " "; cout << endl; } void printArray(const char * array, int count) { for (int ix = 0; ix < count; ix++) cout << array << " "; cout << endl; }

Như vậy, chúng ta có 4 hàm nạp chồng, dành cho các loại dữ liệu khác nhau. Như bạn có thể thấy, chúng chỉ khác nhau ở tiêu đề hàm; phần thân của chúng hoàn toàn giống nhau. Tôi đã viết phần thân hàm một lần cho kiểu int và sao chép nó ba lần cho các kiểu dữ liệu khác.

Và nếu bạn chạy chương trình với các chức năng này, nó sẽ hoạt động bình thường. Bản thân trình biên dịch sẽ xác định hàm nào sẽ được sử dụng khi gọi.

Như bạn có thể thấy, có khá nhiều mã cho một thao tác đơn giản như vậy. Điều gì sẽ xảy ra nếu chúng ta cần lập trình nó như một hàm. Hóa ra với mỗi loại dữ liệu, bạn sẽ phải tạo hàm của riêng mình. Nghĩa là, bản thân bạn hiểu rằng cùng một mã sẽ có nhiều bản sao, điều này không có ích gì đối với chúng tôi. Đó là lý do tại sao C++ đưa ra cơ chế như vậy - các mẫu hàm.

Chúng tôi tạo một mẫu trong đó chúng tôi mô tả tất cả các loại dữ liệu. Bằng cách này, nguồn sẽ không bị lộn xộn với những dòng mã không cần thiết. Dưới đây chúng ta sẽ xem xét một chương trình ví dụ có mẫu hàm. Vì vậy, hãy nhớ điều kiện: “lập trình một hàm hiển thị các phần tử của mảng”.

#bao gồm < count; ix++) cout << array << " "; cout << endl; } // конец шаблона функции printArray int main() { // размеры массивов const int iSize = 10, dSize = 7, fSize = 10, cSize = 5; // массивы разных типов данных int iArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; double dArray = {1.2345, 2.234, 3.57, 4.67876, 5.346, 6.1545, 7.7682}; float fArray = {1.34, 2.37, 3.23, 4.8, 5.879, 6.345, 73.434, 8.82, 9.33, 10.4}; char cArray = {"MARS"}; cout << "\t\t Шаблон функции вывода массива на экран\n\n"; // вызов локальной версии функции printArray для типа int через шаблон cout << "\nМассив типа int:\n"; printArray(iArray, iSize); // вызов локальной версии функции printArray для типа double через шаблон cout << "\nМассив типа double:\n"; printArray(dArray, dSize); // вызов локальной версии функции printArray для типа float через шаблон cout << "\nМассив типа float:\n"; printArray(fArray, fSize); // вызов локальной версии функции printArray для типа char через шаблон cout << "\nМассив типа char:\n";printArray(cArray, cSize); return 0; }

// mã Code::Khối

// Mã Dev-C++

#bao gồm #bao gồm sử dụng không gian tên std; // mẫu hàm printMẫu mảng void printArray(const T * array, int count) ( for (int ix = 0; ix< count; ix++) cout << array << " "; cout << endl; } // конец шаблона функции printArray int main() { // размеры массивов const int iSize = 10, dSize = 7, fSize = 10, cSize = 5; // массивы разных типов данных int iArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; double dArray = {1.2345, 2.234, 3.57, 4.67876, 5.346, 6.1545, 7.7682}; float fArray = {1.34, 2.37, 3.23, 4.8, 5.879, 6.345, 73.434, 8.82, 9.33, 10.4}; char cArray = {"MARS"}; cout << "\t\t Шаблон функции вывода массива на экран\n\n"; // вызов локальной версии функции printArray для типа int через шаблон cout << "\nМассив типа int:\n"; printArray(iArray, iSize); // вызов локальной версии функции printArray для типа double через шаблон cout << "\nМассив типа double:\n"; printArray(dArray, dSize); // вызов локальной версии функции printArray для типа float через шаблон cout << "\nМассив типа float:\n"; printArray(fArray, fSize); // вызов локальной версии функции printArray для типа char через шаблон cout << "\nМассив типа char:\n";printArray(cArray, cSize); return 0; }

Xin lưu ý rằng mã đã được giảm đi 4 lần vì chỉ có một phiên bản của hàm được khai báo trong chương trình - mẫu. Trong main tôi đã khai báo một số mảng - bốn mảng, dành cho các kiểu dữ liệu: int, double, float, char. Sau đó, ở các dòng 26, 28, 30, 32, hàm printArray được gọi cho các mảng khác nhau. Kết quả của chương trình được hiển thị dưới đây.

Mẫu hiển thị mảng lên màn hình Mảng kiểu int: 1 2 3 4 5 6 7 8 9 10 Mảng kiểu double: 1.2345 2.234 3.57 4.67876 5.346 6.1545 7.7682 Mảng kiểu float: 1.34 2.37 3.23 4.8 5.879 6.3 45 73,434 8,82 9,33 10.4 Mảng kiểu char: M A R S

Như bạn có thể thấy, chương trình hoạt động chính xác và để làm được điều này, chúng ta chỉ cần xác định hàm printArray một lần ở dạng quen thuộc với chúng ta. Xin lưu ý rằng trước khi khai báo hàm, ở dòng 5, có mục nhập mẫu sau . Mục này gợi ý rằng hàm printArray thực sự là một mẫu hàm, vì tham số đầu tiên của printArray chứa kiểu dữ liệu const T*, giống hệt như ở dòng 5.

Tất cả các mẫu hàm đều bắt đầu bằng mẫu từ, theo sau là dấu ngoặc nhọn liệt kê các tham số. Mỗi tham số phải được đặt trước bởi lớp từ hoặc tên kiểu dành riêng.

Bản mẫu

Bản mẫu

Bản mẫu

Từ khóa typename cho trình biên dịch biết rằng mẫu sẽ sử dụng kiểu dữ liệu có sẵn như: int, double, float, char, v.v. Và từ khóa class cho trình biên dịch biết rằng mẫu hàm sẽ sử dụng các kiểu dữ liệu tùy chỉnh làm tham số, tức là các lớp học.

Mẫu hàm của chúng tôi sử dụng các kiểu dữ liệu có sẵn, vì vậy ở dòng 5 chúng tôi đã viết mẫu . Thay vì T, bạn có thể thay thế bất kỳ tên nào khác mà bạn có thể nghĩ ra. Chúng ta hãy xem xét kỹ hơn đoạn mã từ chương trình hàng đầu, tôi sẽ đăng riêng.

// mẫu hàm printArray mẫu void printArray(const T * array, int count) ( for (int ix = 0; ix< count; ix++) cout << array << " "; cout << endl; } // конец шаблона функции printArray

Dòng 2 xác định một mẫu có một tham số T và tham số này sẽ có một trong các kiểu dữ liệu tích hợp vì từ khóa tên kiểu được chỉ định.

Bên dưới, ở các dòng 3 - 8, một hàm được khai báo đáp ứng đủ các tiêu chí để khai báo một hàm thông thường, có phần đầu, có thân hàm, phần đầu chứa tên và tham số của hàm, mọi thứ vẫn như bình thường. Nhưng thứ biến hàm này thành một mẫu hàm là một tham số có kiểu dữ liệu T , đây là kết nối duy nhất với mẫu được khai báo trước đó. Nếu chúng ta viết

Void printArray(const int * array, int count) ( for (int ix = 0; ix< count; ix++) cout << array << " "; cout << endl; }

thì đó sẽ là một hàm đơn giản cho một mảng kiểu int .

Vì vậy, trên thực tế, T thậm chí không phải là một kiểu dữ liệu, nó là nơi dành riêng cho bất kỳ kiểu dữ liệu tích hợp nào. Nghĩa là, khi hàm này được gọi, trình biên dịch sẽ phân tích tham số của hàm khuôn mẫu và tạo một thể hiện cho kiểu dữ liệu thích hợp: int, char, v.v.

Vì vậy, bạn nên hiểu rằng ngay cả khi số lượng mã nhỏ hơn, điều này không có nghĩa là chương trình sẽ tiêu tốn ít bộ nhớ hơn. Bản thân trình biên dịch tạo ra các bản sao cục bộ của hàm mẫu và theo đó, lượng bộ nhớ tiêu thụ giống như thể bạn đã tự mình viết tất cả các phiên bản hàm, như trường hợp quá tải.
Tôi hy vọng tôi đã truyền đạt được ý chính về các mẫu hàm cho bạn. Để củng cố tài liệu, chúng ta hãy xem một chương trình ví dụ khác sử dụng mẫu hàm.

#include "stdafx.h" #include #bao gồm < size; ix++) if (max < array) max = array; return max; } int main() { // тестируем шаблон функции searchMax для массива типа char char array = "aodsiafgerkeio"; int len = strlen(array); cout << "Максимальный элемент массива типа char: " << searchMax(array, len) << endl; // тестируем шаблон функции searchMax для массива типа int int iArray = {3,5,7,2,9}; cout << "Максимальный элемент массива типа int: " << searchMax(iArray, 5) << endl; return 0; }

// mã Code::Khối

// Mã Dev-C++

#bao gồm #bao gồm sử dụng không gian tên std; // mẫu hàm để tìm giá trị lớn nhất trong mẫu mảng T searchMax(const T* array, int size) ( T max = array; // giá trị lớn nhất trong mảng for (int ix = 0; ix< size; ix++) if (max < array) max = array; return max; } int main() { // тестируем шаблон функции searchMax для массива типа char char array = "aodsiafgerkeio"; int len = strlen(array); cout << "Максимальный элемент массива типа char: " << searchMax(array, len) << endl; // тестируем шаблон функции searchMax для массива типа int int iArray = {3,5,7,2,9}; cout << "Максимальный элемент массива типа int: " << searchMax(iArray, 5) << endl; return 0; }

Đây là một ví dụ khác về việc sử dụng các mẫu hàm. Mẫu hàm được khai báo ở dòng 5-13. Hàm phải trả về giá trị lớn nhất của mảng nên giá trị trả về thuộc loại T , vì kiểu dữ liệu của mảng không được biết trước. Nhân tiện, một biến max loại T được khai báo bên trong hàm; giá trị tối đa của mảng sẽ được lưu trữ trong đó. Như bạn có thể thấy, kiểu dữ liệu T không chỉ được sử dụng để chỉ định các tham số hàm mà còn để chỉ ra kiểu trả về và cũng có thể được sử dụng tùy ý để khai báo bất kỳ biến nào trong mẫu hàm.

Phần tử tối đa của một mảng kiểu char: s Phần tử tối đa của một mảng kiểu int: 9

Các mẫu hàm cũng có thể bị quá tải bằng các mẫu hàm khác bằng cách thay đổi số lượng tham số được truyền cho hàm. Một đặc điểm khác của quá tải là các hàm mẫu có thể bị quá tải bằng các hàm không phải mẫu thông thường. Nghĩa là, cùng một tên hàm được chỉ định, với cùng tham số, nhưng đối với một kiểu dữ liệu cụ thể và mọi thứ sẽ hoạt động chính xác.

Tôi đang định viết một bài về tất cả các loại cấu trúc dữ liệu thú vị thì hóa ra chúng ta vẫn chưa xem xét một số tính năng rất quan trọng của C++. Mẫu là một trong số đó.

Mẫu là một công cụ rất mạnh mẽ. Các hàm và lớp mẫu có thể đơn giản hóa đáng kể cuộc sống của lập trình viên và tiết kiệm rất nhiều thời gian, công sức và thần kinh. Nếu bạn cho rằng các mẫu đó không phải là một chủ đề quan trọng để nghiên cứu thì hãy biết rằng bạn đã nhầm.

Hàm mẫu

Một ví dụ đơn giản về hàm mẫu:

mã bằng ngôn ngữ c++ Nhập hình vuông (Loại a) ( Loại b; b = a*a; return b; ) int x = 5; int tôi; i = hình vuông(5); thả nổi y = 0,5; phao f; f = bình phương(y);

Nếu chúng ta tạo các hàm theo cách cũ thì chúng ta sẽ phải viết hai hàm khác nhau: cho kiểu int và cho kiểu float. Và nếu bạn cần chức năng tương tự bằng cách sử dụng các loại khác, bạn sẽ phải viết lại. Bằng cách sử dụng các mẫu, bạn có thể giới hạn bản thân chỉ ở một phiên bản của hàm, để lại tất cả công việc bẩn thỉu cho trình biên dịch.

Thay vì sử dụng một loại cụ thể, hàm sử dụng một loại tham số (hay nói cách khác là đối số mẫu). Ở đây tôi gọi loại tham số là Loại định danh. Mã định danh này xuất hiện ba lần trong một hàm: giá trị trả về, đối số của hàm và định nghĩa của biến s. Nghĩa là, Type được sử dụng giống như bất kỳ loại thông thường nào.

Nhưng để mã hoạt động, bạn cần thêm dòng sau trước hàm (Tôi đã trình bày một số tùy chọn cú pháp, tất cả đều hoạt động):

mã bằng ngôn ngữ c++ bản mẫu Mẫu hình vuông (Loại a) < class Type >Mẫu hình vuông (Loại a)< class Type >Gõ hình vuông (Loại a)

Vì vậy, trước hàm phải có từ khóa mẫu và trong ngoặc nhọn, bạn phải chỉ định tên của loại tham số bằng từ khóa lớp. Thay vì từ khóa class, bạn có thể sử dụng type - nói chung là không có sự khác biệt.

Mã định danh loại tham số cũng có thể là bất cứ thứ gì. Chúng ta sẽ thường sử dụng những: TypeA, TypeB, Datatype, T.

Lưu ý quan trọng: Các hàm mẫu phải có đối số để trình biên dịch có thể xác định loại nào sẽ sử dụng.

Bạn có thể sử dụng một số loại tham số trong các mẫu và tất nhiên bạn có thể kết hợp các loại tham số với các loại tiêu chuẩn (bạn chỉ cần quan tâm đến việc truyền đúng loại). Tôi sẽ đưa ra một ví dụ sử dụng hai kiểu tham số TypeA, TypeB và kiểu cơ sở int:

mã bằng ngôn ngữ c++ bản mẫu Ví dụ_hàm TypeB (TypeA a, TypeB b) ( int x = 5; b = a + x; return b; )

Nhưng các hàm mẫu không phải là thứ thú vị nhất mà chúng ta sẽ xem xét hôm nay.

Lớp mẫu

Nói chung, các lớp mẫu được tạo theo cách tương tự như các hàm mẫu - từ khóa mẫu được viết trước tên lớp. Hãy xem xét các lớp mẫu bằng ví dụ về ngăn xếp:

mã bằng ngôn ngữ c++ bản mẫu ngăn xếp lớp ( riêng tư: int top; Loại s; public: stack (): top(0) () void push(Type var) ( top++; s = var; ) Loại pop(); ); bản mẫu Gõ stack::pop() ( Type var = s; top--; return var; ) Ở đây chúng ta định nghĩa

chia sẻ một chồng gồm mười phần tử. Các phần tử này có thể thuộc bất kỳ loại nào, chi tiết hơn ở bên dưới.

Điều duy nhất tôi muốn bạn chú ý là định nghĩa của hàm push và pop. Hàm push được định nghĩa bên trong lớp và hàm pop được định nghĩa bên ngoài. Đối với tất cả các hàm được khai báo bên ngoài lớp, từ khóa mẫu phải được chỉ định. Biểu thức trước tên hàm giống với biểu thức trước tên lớp.

Bây giờ hãy xem cách làm việc với các lớp mẫu:

mã bằng ngôn ngữ c++ cây rơm s1; cây rơm s2; s1.push(3); s1.push(2); s1.pop(); s2.push(0,5);

Khi tạo một đối tượng, sau tên lớp bạn cần đặt dấu ngoặc nhọn để chỉ ra loại mong muốn. Sau đó, các đối tượng được sử dụng như chúng ta đã quen.

Các lớp mẫu có một tính năng tuyệt vời - ngoài các loại tiêu chuẩn, chúng còn có thể hoạt động với các loại tùy chỉnh. Hãy xem xét một ví dụ nhỏ. Để làm điều này, hãy xác định một lớp chiến binh đơn giản:

mã bằng ngôn ngữ c++ lớp chiến binh ( public: int health; Warrior() : health(0) () ); cây rơm S; chiến binh w1; chiến binh w2; chiến binh w3; s.push(w1); s.push(w3); s.pop(); s.push(w2);

Hãy nhìn xem, bây giờ bạn có thể đặt các biến loại chiến binh vào ngăn xếp!!! Có thể bạn không tin tôi, nhưng điều này thật tuyệt vời! Bạn có thể thấy điều này thú vị như thế nào khi chúng ta tạo biểu đồ và cây dựa trên danh sách.

Đó là tất cả theo các mẫu bây giờ. Sau này chúng ta sẽ xem xét các trường hợp phức tạp hơn khi sử dụng các lớp mẫu.