類别範本的簡單應用(用於儲存不同型別資料的類容器)

ivanlee717發表於2024-05-01

類别範本應用

explicit

explicit 是一個關鍵字,用於指定該建構函式是顯式建構函式。在C++中,當一個類的建構函式只有一個引數時,它可以被用於隱式型別轉換,這可能會導致意想不到的行為和潛在的錯誤。為了避免這種情況,可以使用 explicit 關鍵字來宣告該建構函式,表示禁止隱式型別轉換,只能顯式地呼叫該建構函式來建立物件。

#include <iostream>

class MyClass {
public:
    explicit MyClass(int x) {
        std::cout << "Explicit constructor called with " << x << std::endl;
    }
};

void func(MyClass obj) {
    std::cout << "Function called" << std::endl;
}

int main() {
    // 顯式呼叫
    MyClass obj1(10);

    // 隱式呼叫,會觸發顯式建構函式,因為 MyClass 只有一個引數的建構函式,並且使用了 explicit 關鍵字
    // MyClass obj2 = 20; // 編譯錯誤,禁止隱式型別轉換
    MyClass obj3 = MyClass(20); // 顯式呼叫

    // 隱式呼叫,會觸發隱式建構函式
    func(30); // 隱式呼叫建構函式,然後呼叫函式

    return 0;
}

image-20240426104414407

必須顯式的去寫一句例項化的語句才能進行構造。

image-20240426104541272

知道這個explicit關鍵字之後開始應用。

程式碼

設計一個陣列模板類(MyArray),完成對不同型別元素的管理

#pragma once

template<class T>
class MyArray
{
public:
    explicit MyArray(int capacity)
    {
        this->m_Capacity = capacity;
        this->m_Size = 0;
        // 如果 T 是物件,那麼這個物件必須提供預設的建構函式
        pAddress = new T[this->m_Capacity];
    }

    // 複製構造
    MyArray(const MyArray& arr)
    {
        this->m_Capacity = arr.m_Capacity;
        this->m_Size = arr.m_Size;
        this->pAddress = new T[this->m_Capacity];
        for (int i = 0; i < this->m_Size; i++)
        {
            this->pAddress[i] = arr.pAddress[i];
        }
    }

    // 過載[] 運算子  arr[0]
    T& operator [](int index)
    {
        return this->pAddress[index];
    }

    // 尾插法
    void push_back(const T& val)
    {
        if (this->m_Capacity == this->m_Size)
        {
            return;
        }
        this->pAddress[this->m_Size] = val;
        this->m_Size++;
    }

    void pop_back()
    {
        if (this->m_Size == 0)
        {
            return;
        }
        this->m_Size--;
    }

    // 獲取大小的 const 成員函式
    int getSize() const
    {
        return this->m_Size;
    }

    // 析構
    ~MyArray()
    {
        if (this->pAddress != nullptr)
        {
            delete[] this->pAddress;
            this->pAddress = nullptr;
            this->m_Capacity = 0;
            this->m_Size = 0;
        }
    }

private:
    T* pAddress;  // 指向一個堆空間,這個空間儲存真正的資料
    int m_Capacity; // 容量
    int m_Size;   // 大小
};

首先實現的是建構函式,規定好必須顯式的宣告例項化,一個是為了隱式轉換專門構造的一種方法,但其實這個過程並不是計算機進行的隱式,因為我們有專門的程式碼去編譯。還有一個就是複製構造。

T& operator [](int ind) {
	return this->ptr[ind];
}
void push_back(const T& ele) {
	if (this->capacity == this->Msize) {
		return;
	}
	this->ptr[this->Msize] = ele;
	this->Msize++;
}
void pop_back() {
	if (this->Msize == 0) {
		return;
	}
	this->Msize--;
}
int get_size() {
	return this->Msize;
}
~MyArray() {
	if (this->ptr != NULL) {
		delete []this->ptr;
		this->pAddress = NULL;
		this->capacity = 0;
		this->Msize = 0;
	}
}

這段程式碼裡實現了入隊和出隊的功能,並且將之前學的過載運算子也用上了。測試程式碼裡我們試圖呼叫多個建構函式去理解程式碼的過程。

#include <iostream>
#include "MyArray.hpp"
using namespace std;

class Person {
public:
	Person(){}
	Person(string name, int age) {
		this->name = name;
		this->age = age;
	}
public:
	string name;
	int age;
};

void PrintArrayInt(MyArray<int>& arr) {
	for (int i = 0; i < arr.get_size(); i++) {
		cout << arr[i] << " ";
	}
	cout << endl;
}

void PrintArrayPerson(MyArray<Person>& arr) {
	for (int i = 0; i < arr.get_size(); i++) {
		cout << "姓名:" << arr[i].name << " 年齡: " << arr[i].age << endl;
	}
	cout << endl;
}

int main() {
	MyArray<int> ArrayInt(10); //透過顯式轉換
	for (int i = 0; i < 9; i++)
	{
		ArrayInt.push_back(i);
	}
	ArrayInt.push_back(127);
	PrintArrayInt(ArrayInt);

	Person p1("regina", 23);
	MyArray<Person> ArrayPerson(p1);//透過我們構造好的隱式轉換
	Person p2("ivanlee", 20);
	Person p3("daji", 18);
	Person p4("dianwei", 15);
	Person p5("paofu", 24);

	ArrayPerson.push_back(p2);
	ArrayPerson.push_back(p3);
	ArrayPerson.push_back(p4);
	ArrayPerson.push_back(p5);
	PrintArrayPerson(ArrayPerson);
	return 0;
}

image-20240501234937921

相關文章