c++补充

构造函数、析构函数

#include <iostream>
using namespace std;// 构造函数、析构函数
//	---	"构造函数"类比生活中的"出厂设置"	---
//	---	"析构函数"类比生活中的"销毁设置"	---
// 如果我们不写这两种函数,编译器会提供默认的构造函数和析构函数,但是它们是空实现
class Person
{
private:int age;public:// 构造函数(无参)Person(){cout << "构造函数的调用,无参" << endl;}// 构造函数(含参)Person(int a){age = a;cout << "构造函数的调用, 含参" << endl;}// 构造函数(拷贝)Person(const Person& p){this->age = p.age;cout << "构造函数的调用,拷贝" << endl;}// 析构函数~Person(){cout << "析构函数的调用" << endl;}// 查看年龄int getAge() { return age; }
};void test()
{// 括号法//Person p1;		// 默认构造函数调用//Person p2(10);	// 括号法调用构造函数(含参)//Person p3(p2);	// 括号法调用构造函数(拷贝)//cout << p3.getMoney() << endl;	// 结果:10// 显示法Person p1;Person p2 = Person(10);		// 含参构造Person p3 = Person(p2);		// 拷贝构造// 注意事项 1:// Person(10);  // 匿名对象 -- 特点: 当前执行结束后,系统会立即回收掉匿名对象// 注意事项 2:// 不要利用拷贝构造函数去初始化匿名对象,即:Person(p3) 是不对的,// 编译器会认为 Person (p3) === Person p3;// 隐式转换法Person p4 = 10;		// 相当于写了 Person p4 = Person(10);   含参构造Person p5 = p4;		// 相当于写了 Person p5 = Person(p4);   拷贝构造
}int main()
{test();
}

初始化列表

#include <iostream>
using namespace std;// 初始化的方式
//	1. 传统的初始化
//	2. 初始化列表class Person
{
public:int age;int height;/*// 1. 传统初始化操作Person(int a, int b){age = a;height = b;}*/// 2. 初始化列表Person(int a, int b) :age(a), height(b){;	// 用";"表示空语句,仅起占位的作用}
};void test()
{	Person man(28, 180);cout << man.age << endl << man.height << endl;
}int main()
{test();
}

常函数、常对象

#include <iostream>
using namespace std;class Person
{
public:// 常函数:// this指针的本质是"指针常量",指针的指向是不可以修改的// const Person * const this;// 在成员函数后面加 const,修饰的是this指向,让指针指向的值也不可以修改void showPerson() const		// 函数的后面加了一个const,我们称为"常函数"{age = 30;  // 这段代码本质是 this->age = 30; 它是会报错的,因为它不可以修改height = 180;	// 如果非得要修改,请在定义的时候,在前面加上关键字 mutable}// 普通成员函数void change(){age = 40;height = 166;}int age;mutable int height;
};void test1()
{Person p;p.showPerson();
}void test2()
{// 常对象:// 在对象前加上 const,它将变为常对象const Person p;p.age = 22;		// 这里会报错,因为它不允许被修改p.height = 175;		// 这里不会报错,因为 mutable 修饰的 height 是一个特殊的变量// 常对象只能调用常函数p.showPerson();p.change();		// 常对象不可以调用普通成员函数,因为普通成员函数可以修改属性
}int main()
{test1();test2();
}

运算符重载

+ 运算符 重载

#include <iostream>
using namespace std;class Person
{
public:int age;int height;// 通过成员函数进行重载+号// Person p3 = p1 + p2; == Person p3 = p1.operator+(p2);Person operator+(const Person &p){Person temp;temp.age = this->age + p.age;temp.height = this->height + p.height;return temp;}
};// 通过全局函数重载+号
// Person p3 = p1 + p2; == Person p3 = operator+(p1, p2);
Person operator+(const Person& p1, const Person& p2)
{Person temp;temp.age = p1.age + p2.age;temp.height = p1.height + p2.height;return temp;
}void test()
{Person p1;p1.age = 22;p1.height = 166;Person p2;p2.age = 28;p2.height = 134;Person p3 = p1 + p2;	// 加号运算符重载,让编译器知道如何进行运算cout << p3.age << endl << p3.height << endl;	// 输出结果:50、300Person p3 = p3 + 66;	// 编译器不知道如何运行,将会报错!// 运算符重载,也可以使用"函数重载":// 我们可以通过"全局函数重载"实现一个 Person operator+(const Person& p1, int num) {...}// 或者可以通过"成员函数重载"实现一个 Person operator+(int num) {...}// 注意事项:// 1. 对于内置的数据类型的表达式的运算符是不可能改变的// 2. 不用滥用运算符重载
}int main()
{test();
}

<< 运算符 重载

#include <iostream>
using namespace std;class Person
{friend ostream& operator<<(ostream&, const Person&);public:Person(int age, int height) :age(age), height(height){cout << "调用了构造函数" << endl;}private:int age;int height;
};// 无法通过成员函数进行重载<<号
// 只能通过全局函数重载<<号
ostream& operator<<(ostream& cout, const Person& p)
{cout << "[ age = " << p.age << ", height = " << p.height << " ]";return cout;
}void test()
{Person p1(22, 166);cout << p1 << endl;	// 输出结果:[ age = 22, height = 166 ]
}int main()
{test();
}

自增运算符 重载

#include <iostream>
using namespace std;class MyInteger
{friend ostream& operator<<(ostream&, MyInteger);public:MyInteger(int a) :num(a){cout << "调用了构造函数" << endl;}// 前置递增MyInteger& operator++(){num++;return *this;}// 后置递增MyInteger operator++(int)	// int 代表占位参数,可以用于区分前置和后置递增{// 先记录当前结果MyInteger temp = *this;// 后将自己进行递增num++;return temp;}private:int num;
};ostream& operator<<(ostream& cout, MyInteger obj)
{cout << obj.num;return cout;
}void test()
{MyInteger myint = 0;cout << ++(++myint) << endl;	// 输出:2cout << myint << endl;			// 输出:2cout << myint++ << endl;		// 输出:2cout << myint<< endl;			// 输出:3
}int main()
{test();
}

赋值运算符 重载

#include <iostream>
using namespace std;class Person
{
public:Person(int age){this->age = new int(age);}~Person(){if (age != NULL){delete age;age = NULL;}}// 赋值运算符重载Person& operator=(const Person& obj){*age = *obj.age;return *this;}int* age;
};void test()
{Person p1(10);cout << "p1的年龄为:" << *p1.age << endl;	// 输出结果:10Person p2(20);cout << "p2的年龄为:" << *p2.age << endl;	// 输出结果:20Person p3(30);cout << "p3的年龄为:" << *p3.age << endl;	// 输出结果:30// 这不是拷贝构造函数,拷贝构造函数也是一种构造函数// 这里是赋值语句,对象的赋值,编译器默认的行为是:将某对象的所有属性复制一份到另一个对象里面// 因为默认行为的直接复制,对于需要浅拷贝的内容没什么影响,但是对于需要深拷贝的内容影响很大// 为了避免恶劣影响,我们需要重载赋值运算符p3 = p2 = p1;cout << "修改后的p2的年龄为:" << *p2.age << endl;		// 输出结果:10cout << "修改后的p3的年龄为:" << *p3.age << endl;		// 输出结果:10
}int main()
{test();
}

关系运算符 重载

#include <iostream>
#include <string>
using namespace std;class Person
{
public:string name;int age;Person(string name, int age) :name(name), age(age){;	// 空语句}// == 关系运算符重载bool operator==(const Person& obj){if (name == obj.name && age == obj.age){return true;}return false;}// != 关系运算符重载bool operator!=(const Person& obj){if (name == obj.name && age == obj.age){return false;}return true;}};void test()
{Person p1("Jack", 18);Person p2("Jack", 18);Person p3("Tom", 18);if (p1 == p2)	cout << "p1 和 p2 相等" << endl;if (p1 != p3)	cout << "p1 和 p3 不相等" << endl;
}int main()
{test();
}

函数调用运算符 重载

#include <iostream>
#include <string>
using namespace std;class MyPrint
{
public:// 重载函数调用运算符void operator()(string text, string end="\n"){cout << text << end;}
};class MyAdd
{
public:// 重载函数调用运算符int operator()(int a, int b){return a + b;}
};void test()
{MyPrint print;MyAdd add;print("hello world");	// 由于使用起来非常类似于函数调用,因此称为仿函数string res = to_string(add(10, 20));print(res);// 匿名函数对象 -> MyAdd()cout << MyAdd()(100, 100) << endl;
}int main()
{test();
}

继承知识补充

在这里插入图片描述

多态

基础应用

#include <iostream>
#include <string>
using namespace std;class Animal
{
public:virtual void speak(){cout << "动物在叫" << endl;}
};class Cat :public Animal
{
public:void speak(){cout << "猫在叫" << endl;}
};class Dog :public Animal
{
public:void speak(){cout << "狗在叫" << endl;}
};// 地址早绑定,在编译阶段确定函数地址
// 如果想要传入的参数cat能够调用speak(),那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定
void doSpeak(Animal& animal)	// Animal &animal = cat;
{animal.speak();
}void test()
{Cat cat;Dog dog;doSpeak(cat);doSpeak(dog);
}int main()
{test();
}

进阶应用

#include <iostream>
#include <string>
using namespace std;class abstractDrinking
{
public:// 煮水virtual void Boil() = 0;// 冲泡virtual void Brew() = 0;// 倒入杯中virtual void PourInCup() = 0;// 加入辅料virtual void PutSomething() = 0;// 制作饮品void make(){Boil();Brew();PourInCup();PutSomething();}
};// 制作咖啡
class Coffee :public abstractDrinking	// 继承抽象类
{// 必须重写抽象类的纯虚函数,否则自己也会变成抽象类
public:// 煮水virtual void Boil(){cout << "煮熟自来水" << endl;}// 冲泡virtual void Brew(){cout << "冲泡咖啡" << endl;}// 倒入杯中virtual void PourInCup(){cout << "倒入迷你的咖啡杯中" << endl;}// 加入辅料virtual void PutSomething(){cout << "加入一些糖" << endl;}
};// 制作茶水
class Tea :public abstractDrinking	// 继承抽象类
{// 必须重写抽象类的纯虚函数,否则自己也会变成抽象类
public:// 煮水virtual void Boil(){cout << "煮熟矿泉水" << endl;}// 冲泡virtual void Brew(){cout << "冲泡茶叶" << endl;}// 倒入杯中virtual void PourInCup(){cout << "倒入经典的茶杯中" << endl;}// 加入辅料virtual void PutSomething(){cout << "加入一些香料" << endl;}
};// 制作饮料
void makeDrink(abstractDrinking* drink)
{drink->make();delete drink;			// 删除对象,释放内存
}void test()
{// 制作咖啡makeDrink(new Coffee);	// 开辟内存,创建对象// 制作茶makeDrink(new Tea);
}int main()
{test();
}

高级应用 (经典)

#include <iostream>
#include <string>
using namespace std;// ------------------
// 1. 抽象出每个零件(CPU、VideoCard、Memory)
// 2. 具体的厂商零件(Intel、Lenovo)
// 3. 电脑类->提供让电脑工作的函数(Computer)
// 4. 组装三台不同的电脑
// ------------------// 1. 抽象出每个零件
class CPU
{
public:// 抽象计算函数virtual void calculate() = 0;
};class VideoCard
{
public:// 抽象显示函数virtual void display() = 0;
};class Memory
{
public:// 抽象存储函数virtual void storage() = 0;
};// 2. 具体的厂商零件// --- Intel 的 CPU、VideoCard、Memory
class IntelCPU :public CPU
{
public:virtual void calculate()	// 也可以省略 virtual 关键字,直接写成 void calculate(){cout << "Intel 的 CPU 开始工作了" << endl;}
};class IntelVideoCard :public VideoCard
{
public:virtual void display(){cout << "Intel 的 VideoCard 开始工作了" << endl;}
};class IntelMemory :public Memory
{
public:virtual void storage(){cout << "Intel 的 Memory 开始工作了" << endl;}
};// --- Lenovo 的 CPU、VideoCard、Memory
class LenovoCPU :public CPU
{
public:virtual void calculate(){cout << "Lenovo 的 CPU 开始工作了" << endl;}
};class LenovoVideoCard :public VideoCard
{
public:virtual void display(){cout << "Lenovo 的 VideoCard 开始工作了" << endl;}
};class LenovoMemory :public Memory
{
public:virtual void storage(){cout << "Lenovo 的 Memory 开始工作了" << endl;}
};// 3. 电脑类
class Computer
{
public:// 构造函数中传入三个零件指针Computer(CPU* cpu, VideoCard* vc, Memory* mem) : cpu(cpu), vc(vc), mem(mem){;	// 空语句}// 提供工作的函数void work(){cpu->calculate();vc->display();mem->storage();}// 提供析构函数,销毁电脑的时候,释放3个电脑零件~Computer(){// 释放CPU零件if (cpu != NULL){delete cpu;cpu = NULL;}if (vc != NULL){delete vc;vc = NULL;}if (mem != NULL){delete mem;mem = NULL;}}private:CPU* cpu;		// CPU零件指针VideoCard* vc;	// 显卡零件指针Memory* mem;	// 内存条零件指针
};void test()
{// 4. 组装三台不同的电脑// 准备好'第一台电脑'的零件CPU* intelCpu = new IntelCPU;VideoCard* intelCard = new IntelVideoCard;Memory* intelMem = new IntelMemory;// 创建'第一台电脑'Computer* computer1 = new Computer(intelCpu, intelCard, intelMem);computer1->work();// 销毁'第一台电脑'delete computer1;computer1 = NULL;cout << "------------------------------" << endl;// 第二台电脑的组装Computer* computer2 = new Computer(new LenovoCPU, new LenovoVideoCard, new LenovoMemory);computer2->work();// 销毁'第二台电脑'delete computer2;computer2 = NULL;cout << "------------------------------" << endl;// 第三台电脑的组装Computer* computer3 = new Computer(new IntelCPU, new LenovoVideoCard, new LenovoMemory);computer3->work();// 销毁'第三台电脑'delete computer3;computer3 = NULL;
}int main()
{test();
}

文件操作

#include <iostream>
#include <fstream>
#include <string>using namespace std;// 文本文件
// 1. 写文本文件
// 2. 读文本文件// 二进制文件
// 1. 写二进制文件
// 2. 读二进制文件void writeText()
{// 1、包含头文件// 2、创建对象流ofstream file;// 3、打开文件,以追加的方式file.open("test.txt", ios::app);// 4、写内容file << "姓名:张三" << endl;file << "性别:男" << endl;file << "年龄:28" << endl;// 5、关闭文件file.close();
}void readText()
{// 1、包含头文件// 2、创建对象流ifstream file;// 3、打开文件,并判断是否打开成功file.open("test.txt", ios::in);if (!file.is_open()){cout << "文件打开失败!" << endl;return;}// 4、读取内容/*// 方法一:char arr[1024] = { 0 };		// 数组while (file >> arr){cout << arr << endl;}// 方法二:char arr[1024] = { 0 };		// 数组while (file.getline(arr, sizeof(arr))){cout << arr << endl;}// 方法三:string content;while (getline(file, content))		// 调用 <string> 里面的 getline() 方法{cout << content << endl;}*/// 方法四:(不建议)char c;while ((c = file.get()) != EOF)	// EOF: end of file{cout << c;		// 每次读取一个字符,将其输出}// 5、关闭文件file.close();
}class Person
{
public:char m_Name[64];int m_Age;
};void writeBinary()
{// 1、包含头文件// 2、创建流对象ofstream file;// 3、打开文件file.open("person.txt", ios::out | ios::binary);// 4、写文件Person p = { "张三", 28 };file.write((const char*)&p, sizeof(Person));// 5、关闭文件file.close();
}void readBinary()
{// 1、包含头文件// 2、创建流对象ifstream file;// 3、打开文件,判断文件是否打开成功file.open("person.txt", ios::in | ios::binary);if (!file.is_open()){cout << "文件打开失败" << endl;}// 4、读取文件Person p;file.read((char*)&p, sizeof(Person));cout << "姓名:" << p.m_Name << "年龄:" << p.m_Age << endl;// 5、关闭文件file.close();
}int main()
{writeText();readText();writeBinary();readBinary();
}

函数模板的重载

#include <iostream>
#include <string>
using namespace std;class Person
{
public:Person(string name, int age){this->m_Name = name;this->m_Age = m_Age;}string m_Name;int m_Age;
};template<typename T>
bool myCompare(T &a, T &b)
{if (a == b)	return true;else return false;
}// 模板的重载
template<>
bool myCompare(Person& p1, Person& p2)
{if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age)	return true;else return false;
}void test()
{int a = 10;int b = 10;bool ret = myCompare(a, b);cout << ret << endl;		// 输出结果:1Person p1("张三", 18);Person p2("李四", 28);bool res = myCompare(p1, p2);cout << res << endl;		// 输出结果:0
}int main()
{test();
}

类模板

#include <iostream>
#include <string>
using namespace std;// 类模板template<class Type1, class Type2 = int>	// 类模板在模板参数列表中可以有默认参数
class Person
{
public:Person(Type1 name, Type2 age){this->m_Name = name;this->m_Age = age;}void showPerson(){cout << "name: " << m_Name << " age: " << m_Age << endl;}Type1 m_Name;Type2 m_Age;
};void test()
{// ---类模板没有自动类型推导的使用方式Person<string, int> p1("张三", 18);p1.showPerson();// ---类模板在模板参数列表中可以有默认参数Person<string> p2("李四", 28);p2.showPerson();
}int main()
{test();
}
#include <iostream>
#include <string>
using namespace std;template<class T1, class T2>
class Person
{
public:Person(T1 name, T2 age){this->m_Name = name;this->m_Age = age;}void showPerson(){cout << "姓名:" << this->m_Name << " 年龄:" << this->m_Age << endl;}T1 m_Name;T2 m_Age;
};// 类模板对象做函数参数// 1. 指定传入类型
void printPerson1(Person<string, int> &p)
{p.showPerson();
}// 2. 参数模板化
template<class T1, class T2>
void printPerson2(Person<T1, T2>& p)
{p.showPerson();
}// 3. 整个类
template<class T>
void printPerson3(T& p)
{p.showPerson();
}void test()
{Person<string, int> p1("张三", 28);printPerson1(p1);Person<string, int> p2("李四", 18);printPerson2(p2);Person<string, int> p3("王五", 38);printPerson3(p3);
}int main()
{test();
}

类模板与继承

#include <iostream>
#include <string>
using namespace std;// 类模板与继承
template <class T>
class Base
{T m_Name;
};// 必须要知道父类中的T类型,才能继承给子类
class Son : public Base<int>
{};void test1()
{Son s1;
}// 如果想灵活指定父类中T类型,子类也需要变类模板
template <class T1, class T2>
class Son2 : public Base<T2>
{
public:Son2(){cout << "T1 的类型为:" << typeid(T1).name() << endl;cout << "T2 的类型为:" << typeid(T2).name() << endl;}
};void test2()
{Son2<int, char> s2;
}int main()
{test1();test2();
}

类模板函数的类外实现

#include <iostream>
#include <string>
using namespace std;template<class T1, class T2>
class Person
{
public:Person(T1 name, T2 age);void showPerson();T1 m_Name;T2 m_Age;
};// 类模板成员的类外实现(构造函数)
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) :m_Name(name), m_Age(age)
{cout << "构造函数被调用了" << endl;
}
// 类模板成员的类外实现(普通成员函数)
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{cout << "姓名:" << m_Name << "年龄:" << m_Age;
}void test()
{Person<string, int> p("Tom", 28);
}int main()
{test();
}

类模板分文件编写

问题:类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
解决:解决办法1:直接包含.cpp源文件解决办法2:将声明和实现写到同一个文件中,并更改后缀名为.hpp,.hpp是约定的名称,并不是强制
  • main.cpp 文件
#include <string>
using namespace std;// 第一种解决方式:直接包含源文件
#include "person.cpp"// 第二种解决方式:将.h和.cpp中的内容写在一起,将后缀名改为.hpp文件(约定俗成)
// #include "person.hpp"void test()
{Person<string, int> p("Tom", 28);p.showPerson();
}int main()
{test();
}
  • person.cpp 文件
#include <iostream>
#include "person.h"// 类模板成员的类外实现(构造函数)
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) :m_Name(name), m_Age(age)
{std::cout << "构造函数被调用了" << std::endl;
}
// 类模板成员的类外实现(普通成员函数)
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{std::cout << "姓名:" << m_Name << " 年龄:" << m_Age << std::endl;
}
  • person.h 文件
#pragma once	// 只要在头文件的最开始加入这条预处理指令,就能够保证头文件只被编译一次,防止头文件被重复引用template<class T1, class T2>
class Person
{
public:Person(T1 name, T2 age);void showPerson();T1 m_Name;T2 m_Age;
};

类模板与友元

#include <iostream>
#include <string>
using namespace std;// 总结:
// 1. 全局函数,如果在类外实现的话,比较简单;如果在类外实现的话,比较复杂,需要提前让编译器知道全局函数的存在
// 2. 建议使用类内实现的方式,简单易懂// 提前让编译器知道Person类存在(才能实现全局函数,内类声明,类外实现)
template <class T1, class T2>
class Person;// 全局函数,内类声明,类外实现(这个函数模板实现必须要在类实现之前)
template <class T1, class T2>
void printPerson2(Person<T1, T2> p)
{cout << "姓名:" << p.m_Name << " 年龄:" << p.m_Age << endl;
}template <class T1, class T2>
class Person
{// 全局函数,类内实现friend void printPerson(Person<T1, T2> p){cout << "姓名:" << p.m_Name << " 年龄:" << p.m_Age << endl;}// 全局函数,类内声明,类外实现// 因为类型不一样(实现是函数模板,而声明是函数),所以需要加上空模板参数列表// 让它统一类型才不会报错,最终是(实现是函数模板,声明也是函数模板)friend void printPerson2<>(Person<T1, T2> p);public:Person(T1 name, T2 age) :m_Name(name), m_Age(age){cout << "成功构造了一个对象" << endl;}private:T1 m_Name;T2 m_Age;
};void test()
{// 全局函数,类内实现Person<string, int> p1("Jack", 29);printPerson(p1);// 全局函数,类外实现Person<string, int> p2("Tom", 30);printPerson2(p2);
}int main()
{test();
}

模板案例

  • main.cpp 文件
#include <iostream>
#include <string>
#include "MyArray.hpp"
using namespace std;// 基本数据类型-数组测试
void test1()
{// 创建一个int类型,数组长度为10的数组对象 arr1MyArray<int> arr1(10);			// 调用构造函数MyArray<int> arr2 = arr1;		// 调用拷贝构造函数MyArray<int> arr3(20);arr3 = arr1;					// 赋值运算符重构bool ret;for (int i = 0; i < arr3.getCapacity(); i++){ret = arr3.append(100 - i);		// 尾追加cout << ret << endl;}cout << "----------" << endl;arr3.pop();						// 尾删除cout << arr3[9] << endl;		// []运算符重载		输出结果:91arr3[9] = 666;cout << arr3[9] << endl;		// []运算符重载		输出结果:666
}// 自定义数据类型-数组测试
class Person
{
public:Person() {}Person(string name, int age){this->m_Name = name;this->m_Age = age;}string m_Name;int m_Age;
};void test2()
{MyArray<Person> arr(3);Person p1("Jack", 25);Person p2("Tom", 28);Person p3("Jim", 29);// 将数据插入到数组中arr.append(p1);arr.append(p2);arr.append(p3);// 打印数组for (int i = 0; i < arr.getCapacity(); i++){cout << "姓名:" << arr[i].m_Name << "\t年龄:" << arr[i].m_Age << endl;}
}int main()
{// 基本数据类型-数组测试test1();cout << "*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*" << endl;// 自定义数据类型-数组测试test2();system("pause");return 0;
}/*运行结果:1111111111----------91666*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*姓名:Jack      年龄:25姓名:Tom       年龄:28姓名:Jim       年龄:29
*/
  • MyArray.hpp 文件
// 实现一个通用的数组类
#pragma once
#include <iostream>
#include <string>template <class T>
class MyArray
{
private:T* pAddress;		// 指针指向堆区开辟的真实数组int m_Capacity;		// 数组容量int m_Size;			// 数组元素个数public:// 构造函数MyArray(int capacity){this->m_Capacity = capacity;this->m_Size = 0;this->pAddress = new T[this->m_Capacity];}// 析构函数~MyArray(){if (this->pAddress != NULL){delete[] this->pAddress;this->pAddress = NULL;}}// 拷贝构造/*针对以下问题:MyArray<int> arr1(8);MyArray<int> arr2 = arr1;*/MyArray(const MyArray& arr){this->m_Capacity = arr.m_Capacity;this->m_Size = arr.m_Size;// 深拷贝this->pAddress = new T[arr.m_Capacity];for (int i = 0; i < arr.m_Size; i++){this->pAddress[i] = arr.pAddress[i];}}// 赋值运算符重构/*针对以下问题:MyArray<int> arr1(11), arr2(8), arr3(13);arr1 = arr2 = arr3;*/MyArray& operator=(const MyArray& arr){// 先判断原来堆区是否有数据,如果有先释放if (this->pAddress != NULL){delete[] this->pAddress;this->pAddress = NULL;this->m_Capacity = 0;this->m_Size = 0;}this->m_Capacity = arr.m_Capacity;this->m_Size = arr.m_Size;// 深拷贝this->pAddress = new T[arr.m_Capacity];for (int i = 0; i < arr.m_Size; i++){this->pAddress[i] = arr.pAddress[i];}return *this;}// 尾追加/*针对以下问题:MyArray<int> arr1(8);arr1.append()*/bool append(const T& value){// 判断是否已经满了,如果满了,无法插入if (this->m_Size == this->m_Capacity)	return false;// 插入操作this->pAddress[m_Size] = value;m_Size++;return true;}// 尾删除/*针对以下问题:MyArray<int> arr1(8);arr1.pop()*/void pop(){// 判断数组是否为空if (this->m_Size == 0)	return;// 删除操作m_Size--;}// []运算符重构/*针对以下问题:通过下标的方式"访问"数组中的元素 cout << a[0] << endl;通过下标的方式"修改"数组中的元素 a[0] = 99;*/T& operator[](int index){return this->pAddress[index];}// 获取元素个数int getSize(){return this->m_Size;}// 获取数组容量int getCapacity(){return this->m_Capacity;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/635955.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

layui框架实战案例(27):弹出二次验证

HTML容器 <button class"layui-btn layui-btn-sm layui-btn-danger" lay-event"delete"><i class"layui-icon layui-icon-delete"></i>批量删除</button>删除封装函数 function delAll(school_id, school_name) {var lo…

开源贡献代码之​探索一下CPython

探索一下Cython 本篇文章将会围绕最近给Apache提的一个feature为背景&#xff0c;展开讲讲CPython遇到的问题&#xff0c;以及尝试自己从0写一个库出来&#xff0c;代码也已经放星球了&#xff0c;感兴趣的同学可以去下载学习。 0.背景 最近在给apache arrow提的一个feature因为…

zabbix自定义监控、自动发现和注册以及代理设置

前言 监控项的定制和新设备的注册往往需要大量手动操作&#xff0c;这会导致维护成本的增加和监控效率的降低。本文将介绍如何利用 Zabbix 的自定义功能&#xff0c;实现监控项的动态发布和新设备的自动注册以及代理设置、从而简化运维工作并实现更高效的监控管理。 Zabbix 监…

通义千问 Qwen-14B 模型微调实战案例及经验总结

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总…

网络安全产品---数据库防火墙/审计

数据库防火墙 防火墙的类型繁多&#xff0c;即使下一代防火墙或者说AI防火墙集成功能再多&#xff0c;我觉得waf与数据库防火墙也有其无法被替代的理由&#xff0c;以此记录我对数据库防火墙的理解 what 数据库防火墙是基于数据库协议分析与访问行为控制的数据库安全防护产品…

安居水站:独立审慎的批判思考-审辩式思维

正文共:2492字 15张图 预计阅读时间:5分钟 在设计这个教案时&#xff0c;我们的目标是培养出具有独立思考、逻辑思维和批判性分析能力的学生。这些技能是当今社会日益重视的&#xff0c;也是当前教育体系中学生所普遍缺乏的。为此&#xff0c;我们的教案将通过一系列的活…

在PostgreSQL中如何进行全文搜索,以及如何优化全文搜索性能?

文章目录 如何进行全文搜索1. 创建全文搜索向量2. 执行全文搜索查询 如何优化全文搜索性能1. 使用GIN索引2. 限制搜索范围3. 优化文本处理4. 使用并发搜索5. 监控和调整配置 在PostgreSQL中&#xff0c;全文搜索通常通过使用tsvector和tsquery类型&#xff0c;以及to_tsvector和…

分类预测 | Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类预测

分类预测 | Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类预测 目录 分类预测 | Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现SCSO-SVM沙猫群优化算法优化支持向量机多特征分类…

嵌入式学习55-ARM4(ADC和I²C)

1、什么是ADC,模拟量和数字量有什么特点&#xff1f; ADC&#xff1a; …

部署轻量级Gitea替代GitLab进行版本控制(一)

Gitea 是一款使用 Golang 编写的可自运营的代码管理工具。 Gitea Official Website gitea: Gitea的首要目标是创建一个极易安装&#xff0c;运行非常快速&#xff0c;安装和使用体验良好的自建 Git 服务。我们采用Go作为后端语言&#xff0c;这使我们只要生成一个可执行程序即…

启动 UE4编辑器报 加载 Plugin 失败

启动 UE4编辑器报 加载 Plugin 失败&#xff0c;报如下错误&#xff1a; Plugin ‘SteamVR’ failer to load because module ‘SteamVR’ could not be found. Please ensure the plugin is properly installed, otherwise consider disabling the plugin for this project. …

vscode设置conda默认python环境,简单有效

本地conda 可能安装了各种环境&#xff0c;默认的vscode总是base环境&#xff0c;这时你想要在vscode调试python代码&#xff0c;使用默认的环境没有安装对应的包就会遇到报错解决这个问题的方法很简单ctrlshiftp 调出命令面板 再输入 select interpreter , 选择 python 选择解…