Cara Menggunakan Template C++

pengantar

Dalam pemrograman C++ dasar, tipe data, misalnya, int atau char, harus ditunjukkan dalam deklarasi atau definisi. Nilai seperti 4 atau 22 atau -5 adalah sebuah int. Nilai seperti ‘A’ atau ‘b’ atau ‘c’ adalah karakter. Mekanisme template memungkinkan programmer untuk menggunakan tipe generik untuk satu set tipe aktual. Misalnya, programmer dapat memutuskan untuk menggunakan pengenal T untuk int atau char. Algoritma C++ dapat memiliki lebih dari satu tipe generik. Dengan, katakanlah, T untuk int atau char, U dapat berdiri untuk tipe float atau pointer. Kelas, seperti kelas string atau vektor, seperti tipe data, dan objek yang dipakai seperti nilai tipe data, yang merupakan kelas yang ditentukan. Jadi, mekanisme template juga memungkinkan programmer untuk menggunakan pengenal tipe generik untuk satu set kelas.

Template C++ membuat algoritme yang tidak bergantung pada jenis data yang digunakan. Jadi, algoritma yang sama, dengan banyak kemunculan dari tipe yang sama, dapat menggunakan tipe yang berbeda pada eksekusi yang berbeda. Entitas variabel, fungsi, struct, dan kelas dapat memiliki template. Artikel ini menjelaskan cara mendeklarasikan template, cara mendefinisikan template, dan cara menerapkannya di C++. Anda seharusnya sudah memiliki pengetahuan tentang entitas yang disebutkan di atas untuk memahami topik yang dibahas dalam artikel ini.

Jenis

skalar

Jenis skalar adalah void, bool, char, int, float, dan pointer.

Kelas sebagai Tipe

Kelas tertentu dapat dianggap sebagai tipe dan objeknya sebagai nilai yang mungkin.

Tipe generik mewakili satu set tipe skalar. Daftar jenis skalar sangat luas. Tipe int, misalnya, memiliki tipe terkait lainnya, seperti short int, long int, dll. Tipe generik juga dapat mewakili satu set kelas.

Variabel

Contoh deklarasi dan definisi template adalah sebagai berikut:

template<typename T>
        T pi = 3.14;

Sebelum melanjutkan, perhatikan bahwa pernyataan semacam ini tidak dapat muncul di fungsi main() atau cakupan blok apa pun. Baris pertama adalah deklarasi template-head, dengan nama tipe generik yang dipilih programmer, T. Baris berikutnya adalah definisi pengidentifikasi, pi, yang merupakan tipe generik, T. Precision, apakah T adalah sebuah int atau float atau tipe lainnya, dapat dilakukan dalam fungsi C++ main() (atau beberapa fungsi lainnya). Presisi seperti itu akan dilakukan dengan variabel pi, dan bukan T.

Baris pertama adalah deklarasi template-head. Deklarasi ini dimulai dengan kata yang dicadangkan, templat, dan kemudian kurung sudut terbuka dan tertutup. Di dalam kurung sudut, setidaknya ada satu pengenal tipe generik, seperti T, di atas. Mungkin ada lebih dari satu pengidentifikasi tipe generik, dengan masing-masing didahului oleh kata yang dicadangkan, nama ketik. Tipe generik seperti itu di posisi itu disebut parameter templat.

Pernyataan berikut dapat ditulis dalam main() atau fungsi lainnya:

cout << pi<float> << 'n';

Dan fungsinya akan menampilkan 3.14. Ekspresi pi<float> menentukan tipe T yang tepat untuk variabel pi. Spesialisasi memutuskan tipe data tertentu untuk parameter template. Instansiasi adalah proses internal C++ untuk membuat tipe tertentu, seperti float, dalam hal ini. Jangan bingung antara membuat parameter template dan membuat instance kelas. Dalam topik template, banyak tipe data dapat memiliki satu nama tipe generik, sementara banyak kelas dapat memiliki satu nama kelas generik. Namun, nama kelas generik untuk kelas hanya disebut sebagai kelas, dan bukan sebagai nama kelas. Juga, nilai adalah tipe data, seperti int, sebagai objek instantiated ke kelas, seperti kelas String.

Pada spesialisasi, tipe data yang dipilih, seperti float, ditempatkan dalam kurung sudut setelah variabel. Jika ada lebih dari satu parameter template dalam deklarasi template-head, akan ada jumlah tipe data yang sesuai dalam urutan yang sama dalam ekspresi spesialisasi.

Pada spesialisasi, sebuah tipe dikenal sebagai argumen template. Jangan bingung antara argumen ini dan argumen fungsi untuk pemanggilan fungsi.

Jenis Default

Jika tidak ada tipe yang diberikan pada spesialisasi, tipe default diasumsikan. Jadi, dari ekspresi berikut:

    template<typename U = const char*>
        U pi = "love";

the display from:

    cout << pi<> << 'n';

adalah “cinta” untuk pointer konstan ke char. Perhatikan dalam deklarasi bahwa U = const char*. Kurung sudut akan koso
ng pada spesialisasi (tidak ada jenis yang diberikan); tipe aktual dianggap sebagai pointer const ke char, tipe default. Jika beberapa tipe lain diperlukan pada spesialisasi, maka nama tipe akan ditulis dalam kurung sudut. Ketika tipe default diinginkan pada spesialisasi, pengulangan tipe dalam kurung sudut adalah opsional, yaitu, kurung sudut dapat dibiarkan kosong.

Catatan: tipe default masih dapat diubah pada spesialisasi dengan memiliki tipe yang berbeda.

struktur

Contoh berikut menunjukkan bagaimana parameter template dapat digunakan dengan struct:

    template<typename T> struct Ages
        {
            T John = 11;
            T Peter  = 12;
            T Mary  = 13;
            T Joy   = 14;
        };

Ini adalah usia siswa di kelas (kelas). Baris pertama adalah deklarasi template. Tubuh dalam kurung kurawal adalah definisi sebenarnya dari template. Usia dapat ditampilkan dalam fungsi main() dengan yang berikut:

    Ages<int> grade7;
    cout << grade7.John << ' ' << grade7.Mary << 'n';

Outputnya adalah: 11 13. Pernyataan pertama di sini melakukan spesialisasi. Perhatikan cara pembuatannya. Itu juga memberi nama untuk objek struct: grade7. Pernyataan kedua memiliki ekspresi objek struct biasa. Sebuah struct seperti kelas. Di sini, Ages seperti nama kelas, sedangkan grade7 adalah objek dari kelas (struct).

Jika beberapa usia adalah bilangan bulat dan yang lainnya adalah float, maka struct membutuhkan dua parameter umum, sebagai berikut:

    template<typename T, typename U> struct Ages
        {
            T John = 11;
            U Peter  = 12.3;
            T Mary  = 13;
            U Joy   = 14.6;
        };

Kode yang relevan untuk fungsi main() adalah sebagai berikut:

    Ages<int, float> grade7;
    cout << grade7.John << ' ' << grade7.Peter << 'n';

Outputnya adalah: 11 12.3. Pada spesialisasi, urutan tipe (argumen) harus sesuai dengan urutan tipe generik dalam deklarasi.

Deklarasi template dapat dipisahkan dari definisi, sebagai berikut:

    template<typename T, typename U> struct Ages
        {
            T John;
            U Peter;
            T Mary;
            U Joy;
        };

    Ages<int, float> grade7 = {11, 12.3, 13, 14.6};

Segmen kode pertama adalah murni deklarasi template (tidak ada tugas). Segmen kode kedua, yang hanya merupakan pernyataan, adalah definisi pengenal, grade7. Sisi kiri adalah deklarasi pengidentifikasi, grade7. Sisi kanan adalah daftar penginisialisasi, yang memberikan nilai yang sesuai ke anggota struct. Segmen kedua (pernyataan) dapat ditulis dalam fungsi main(), sedangkan segmen pertama tetap berada di luar fungsi main().

Non-Tipe

Contoh tipe non-data termasuk int, pointer ke objek, pointer ke fungsi, dan tipe otomatis. Ada non-jenis lain, yang artikel ini tidak membahas. Non-tipe seperti tipe yang tidak lengkap, yang nilainya diberikan kemudian dan tidak dapat diubah. Sebagai parameter, itu dimulai dengan non-tipe tertentu, diikuti oleh pengidentifikasi. Nilai pengenal diberikan kemudian, pada spesialisasi, dan tidak dapat diubah lagi (seperti konstanta, yang nilainya diberikan kemudian). Program berikut menggambarkan hal ini:

#include <iostream>
using namespace std;

    template<typename T, typename U, int N> struct Ages
        {
            T John = N;
            U Peter = 12.3;
            T Mary = N;
            U Joy  = 14.6;
        };

int main()
{
    Ages<int, float, 11> grade7;

    cout << grade7.John << ' ' << grade7.Joy << 'n';

    return 0;
}

Pada spesialisasi, tipe pertama, int, dalam kurung sudut ada lebih untuk formalitas, untuk memastikan bahwa jumlah dan urutan parameter sesuai dengan jumlah dan urutan tipe (argumen). Nilai N telah diberikan pada spesialisasi. Outputnya adalah: 11 14.6.

Spesialisasi Parsial

Mari kita asumsikan bahwa sebuah template memiliki empat tipe generik dan bahwa, di antara empat tipe tersebut, ada kebutuhan untuk dua tipe default. Ini dapat dicapai dengan menggunakan konstruksi spesialisasi parsial, yang tidak menggunakan operator penugasan. Jadi, konstruksi spesialisasi parsial memberikan nilai default ke subset tipe generik. Namun, dalam skema spesialisasi parsial, diperlukan kelas dasar (struct) dan kelas spesialisasi parsial (struct). Program berikut mengilustrasikan ini untuk satu tipe generik dari dua tipe generik:

#include <iostream>
using namespace std;

//base template class
template<typename T1, typename T2>
struct Ages
{
};

//partial specialization
template<typename T1>
struct Ages<T1, float>
{
            T1 John = 11;
            float Peter  = 12.3;
            T1 Mary  = 13;
            float Joy   = 14.6;
};

int main()
{
    Ages<int, float> grade7;
    cout << grade7.John << ' ' << grade7.Joy << 'n';

    return 0;
}

Identifikasi deklarasi kelas dasar dan definisi kelas parsialnya. Deklarasi template-head dari kelas dasar memiliki semua parameter generik yang diperlukan. Deklarasi template-head dari kelas spesialisasi parsial hanya memiliki tipe generik. Ada satu set tambahan kurung sudut yang digunakan dalam skema yang muncul tepat setelah nama kelas dalam definisi spesialisasi parsial. Inilah yang sebenarnya melakukan spesialisasi parsial. Ini memiliki tipe default dan tipe non-default, dalam urutan yang ditulis di kelas dasar. Perhatikan bahwa tipe default masih dapat diberikan tipe yang berbeda dalam fungsi main().

Kode yang relevan dalam fungsi main() dapat berupa sebagai berikut:

    Ages<int, float> grade7;
    cout << grade7.John << ' ' << grade7.Joy << 'n';

Outputnya adalah: 11 14.6.

Paket Parameter Template

Paket parameter adalah parameter templat yang menerima nol atau lebih tipe generik templat untuk tipe data terkait. Parameter paket parameter dimulai dengan nama jenis atau kelas kata yang dicadangkan. Ini diikuti oleh tiga titik, dan kemudian pengidentifikasi untuk paket. Program berikut mengilustrasikan bagaimana paket parameter template dapat digunakan dengan struct:

#include <iostream>
using namespace std;

    template<typename... Types> struct Ages
        {
            int John = 11;
            float Peter  = 12.3;
            int Mary  = 13;
            float Joy   = 14.6;
        };

int main()
{

    Ages<int> gradeB;
    cout << gradeB.John << ' ' << gradeB.Mary << 'n';

    Ages<float> gradeC;
    cout << gradeC.Peter << ' ' << gradeC.Joy << 'n';

    Ages<int, float> gradeD;
    cout << gradeD.John << ' ' << gradeD.Joy << 'n';

    Ages<> gradeA;  //like default
    cout << gradeA.John << ' ' << gradeA.Joy << 'n';

    return 0;
}

Outputnya adalah:

11 13
12.3 14.6
11 14.6
11 14.6

Template Fungsi

Fitur template yang disebutkan di atas berlaku dengan cara yang mirip dengan template fungsi. Program berikut menunjukkan sebuah fungsi dengan dua parameter template generik dan tiga argumen:

#include <iostream>
using namespace std;

    template<typename T, typename U> void func (T no, U cha, const char *str )
        {
            cout << "There are " << no << " books worth " << cha << str << " in the store." << 'n';
        }

int main()
{
    func(12, '$', "500");

    return 0;
}

Outputnya adalah sebagai berikut:

Ada 12 buku senilai $500 di toko.

Pemisahan dari Prototipe

Definisi fungsi dapat dipisahkan dari prototipenya, seperti yang ditunjukkan oleh program berikut:

#include <iostream>
using namespace std;

    template<typename T, typename U> void func (T no, U cha, const char *str );

    template<typename T, typename U> void func (T no, U cha, const char *str )
        {
            cout << "There are " << no << " books worth " << cha << str << " in the store." << 'n';
        }

int main()
{

    func(12, '$', "500");

    return 0;
}

Catatan: Deklarasi template fungsi tidak dapat muncul di fungsi main() atau fungsi lainnya.

kelebihan beban

Overloading dari fungsi yang sama dapat terjadi dengan deklarasi template-head yang berbeda. Program berikut menggambarkan hal ini:

#include <iostream>
using namespace std;

    template<typename T, typename U> void func (T no, U cha, const char *str )
        {
            cout << "There are " << no << " books worth " << cha << str << " in the store." << 'n';
        }

    template<typename T> void func (T no, const char *str )
        {
          & nbsp; cout << "There are " << no << " books worth $" << str << " in the store." << 'n';
        }

int main()
{
    func(12, '$', "500");
    func(12, "500");

    return 0;
}

Outputnya adalah:

Ada 12 buku senilai $500 di toko.

Ada 12 buku senilai $500 di toko.

Template Kelas

Fitur template yang disebutkan di atas berlaku dengan cara yang mirip dengan template kelas. Program berikut adalah deklarasi, definisi, dan useran kelas sederhana:

#include <iostream>
using namespace std;

    class TheCla
        {
            public:
            int num;
            static char ch;

            void func (char cha, const char *str)
                {
                    cout << "There are " << num << " books worth " << cha << str << " in the store." << 'n';
                }
            static void fun (char ch)
                {
                    if (ch == 'a')
                        cout << "Official static member function" << 'n';
                }
        };

int main()
{
    TheCla obj;
    obj.num = 12;
    obj.func('$', "500");

    return 0;
}

Outputnya adalah sebagai berikut:

Ada 12 buku senilai $500 di toko.

Program berikut adalah program di atas dengan deklarasi template-head:

#include <iostream>
using namespace std;

    template<class T, class U> class TheCla
        {
            public:
            T num;
            static U ch;

            void func (U cha, const char *str)
                {
                    cout << "There are " << num << " books worth " << cha << str << " in the store." << 'n';
                }
            static void fun (U ch)
                {
                    if (ch == 'a')
                        cout << "Official static member function" << 'n';
                }
        };

int main()
{
    TheCla<int, char> obj;
    obj.num = 12;
    obj.func('$', "500");

    return 0;
}

Alih-alih nama jenis kata dalam daftar parameter templat, kelas kata dapat digunakan. Perhatikan spesialisasi dalam deklarasi objek. Outputnya masih sama:

Ada 12 buku senilai $500 di toko.

Memisahkan Deklarasi

Deklarasi template kelas dapat dipisahkan dari kode kelas, sebagai berikut:

template<class T, class U> class TheCla;

    template<class T, class U> class TheCla
        {
            public:
            T num;
            static U ch;

            void func (U cha, const char *str)
                {
                    cout << "There are " << num << " books worth " << cha << str << " in the store." << 'n';
                }
            static void fun (U ch)
                {
                    if (ch == 'a')
                        cout << "Official static member function" << 'n';
                }
        };

Berurusan dengan Anggota Statis

Program berikut menunjukkan cara mengakses anggota data statis dan fungsi anggota statis:

#include <iostream>
using namespace std;

    template<class T, class U> class TheCla
        {
            public:
            T num;
            static U ch;

            void func (U cha, const char *str)
                {
                    cout << "There are " << num << " books worth " << cha << str << " in the store." << 'n';
                }
            static void fun (U cha)
                {
                    if (ch == 'a')
                        cout << "Official static member function" << cha << 'n';
                }
        };

    template<class T, class U> U TheCla<T, U>::ch = 'a';

int main()
{
    TheCla<int, char>::fu n('.');

    return 0;
}

Menetapkan nilai ke anggota data statis adalah deklarasi dan tidak boleh di main(). Perhatikan useran dan posisi tipe generik dan tipe generik data dalam pernyataan penugasan. Selain itu, perhatikan bahwa fungsi anggota data statis telah dipanggil di main(), dengan tipe data template yang sebenarnya. Outputnya adalah sebagai berikut:

Fungsi anggota statis resmi.

kompilasi

Deklarasi (header) dan definisi template harus dalam satu file. Artinya, mereka harus berada dalam satuan terjemahan yang sama.

Kesimpulan

Template C++ membuat algoritme independen dari jenis data yang digunakan. Entitas variabel, fungsi, struct, dan kelas dapat memiliki template, yang melibatkan deklarasi dan definisi. Membuat template juga melibatkan spesialisasi, yaitu ketika tipe generik mengambil tipe aktual. Deklarasi dan definisi template harus berada dalam satu unit terjemahan.

Related Posts