类模板应用
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;
}
必须显式的去写一句实例化的语句才能进行构造。
知道这个explicit关键字之后开始应用。
代码
设计一个数组模板类(MyArray),完成对不同类型元素的管理
#pragma oncetemplate<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;
}