c++补充

news/2024/9/20 1:17:34/ 标签: 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.ppmy.cn/news/1433431.html

相关文章

OpenHarmony多媒体-metadata-extractor

简介 metadata-extractor是用于从图像、视频和音频文件中提取 Exif、IPTC、XMP、ICC 和其他元数据的组件。 下载安装 ohpm install ohos/metadata-extractorOpenHarmony ohpm环境配置等更多内容&#xff0c;请参考 如何安装OpenHarmony ohpm包 。 使用说明 引入文件及代码依…

深入理解Java消息中间件-消息的过滤和选择

在我们如今这个数据驱动的时代&#xff0c;从无数的信息中准确地过滤和选择出对我们最有价值的消息&#xff0c;是业务和技术领域中不可或缺的一个环节。本文我们将探讨消息的过滤和选择是如何实现的&#xff0c;同时简要介绍其背后的原理。 理解消息过滤和选择的重要性 首先…

Maven的下载和环境变量的配置

1下载 maven官网https://maven.apache.org/index.html点击Download 这个是Windows的下载版本&#xff0c;一般是最新的版本&#xff0c; 老的版本下载 以下是对应的老版本下载链接 下载好后是一个压缩包的形式 点击他进行解压到想放的文件夹中&#xff0c;&#xff08;一般不…

Maven基础篇3

Maven进阶 –分模块开发与设计 –聚合 –继承 –属性 –私服 1.分模块开发与设计 开发的时候是分包开发 一个人完成一个包即可&#xff1b; 甚至一个包需要多个人开发&#xff1b;需要对包进行拆分&#xff1b; 也就是将我们一个包的东西&#xff0c;拆分成一个工程&a…

神经网络进阶学习文章(一)

1.讲解YOLO有关知识 深入浅出Yolo系列之Yolov5核心基础知识完整讲解 - 知乎 (zhihu.com) 2.目标检测算法综述 目标检测算法综述 - 知乎 (zhihu.com) 3.TensorFlow详解&#xff0c;当然现在用的最多的是Pytorch框架了 谷歌大神带你十分钟看懂TensorFlow - 知乎 (zhihu.co…

ROS1快速入门学习笔记 - 04创建工作环境与功能包

一、定义 工作空间(workspace)是一个存放工程开发相关文件的文件夹。 src:代码空间&#xff08;Source Space&#xff09;build: 编辑空间&#xff08;Build Space&#xff09;devel:开发空间&#xff08;Development Space&#xff09;install:安装空间&#xff08;Install …

Laravel 6 - 第十六章 Artisan命令

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

Linux shell编程学习笔记47:lsof命令

0 前言 今天国产电脑提示磁盘空间已耗尽&#xff0c;使用用df命令检查文件系统情况&#xff0c;发现/dev/sda2已使用100%。 Linux shell编程学习笔记39&#xff1a;df命令https://blog.csdn.net/Purpleendurer/article/details/135577571于是开始清理磁盘空间。 第一步是查看…

服务器防入侵的方案浅析

随着物联网技术和互联网技术的日益发展&#xff0c;勒索病毒、工控安全、产线作业都面领着极大的威胁。智慧互联正在成为各个行业未来的发展方向&#xff0c;智慧互联包括物联网、万物互联&#xff0c;机器与机器&#xff0c;工业控制体系&#xff0c;信息化&#xff0c;也就是…

XiaodiSec day007 Learn Note 小迪安全学习笔记

XiaodiSec day007 Learn Note 小迪安全学习笔记 记录得比较凌乱&#xff0c;不尽详细 07 2023.12.31 cms识别 资产泄漏&#xff0c;资产即为网站的资源&#xff0c;了解到网站使用了那种cms对信息收集很有帮助 使用工具识别cms 识别cms后可以进行代码审计&#xff0c;或…

【RAG 论文】面向知识库检索进行大模型增强的框架 —— KnowledGPT

论文&#xff1a;KnowledGPT: Enhancing Large Language Models with Retrieval and Storage Access on Knowledge Bases ⭐⭐⭐⭐ 复旦肖仰华团队工作 论文速读 KnowledGPT 提出了一个通过检索知识库来增强大模型生成的 RAG 框架。 在知识库中&#xff0c;存储着三类形式的知…

数据库之数据库恢复技术思维导图+大纲笔记

大纲笔记&#xff1a; 事务的基本概念 事务 定义 用户定义的一个数据库操作系列&#xff0c;这些操作要么全做&#xff0c;要么全不做&#xff0c;是一个不可分割的基本单位 语句 BEGIN TRANSACTION 开始 COMMIT 提交&#xff0c;提交事务的所有操作 ROLLBACK 回滚&#xff0c…

BM25检索算法 python

1.简介 BM25&#xff08;Best Matching 25&#xff09;是一种经典的信息检索算法&#xff0c;是基于 TF-IDF算法的改进版本&#xff0c;旨在解决、TF-IDF算法的一些不足之处。其被广泛应用于信息检索领域的排名函数&#xff0c;用于估计文档D与用户查询Q之间的相关性。它是一种…

【AngularJs】前端使用iframe预览pdf文件报错

<iframe style"width: 100%; height: 100%;" src"{{vm.previewUrl}}"></iframe> 出现报错信息&#xff1a;Cant interpolate: {{vm.previewUrl}} 在ctrl文件中信任该文件就可以了 vm.trustUrl $sce.trustAsResourceUrl(vm.previewUrl);//信任…

CSS基础——1.CSS样式

CSS 是“Cascading Style Sheet”的缩写,中文意思为“层叠样式表”,用于描述网页的表现形式(例如网页元素的位置、大小、颜色等。css的主要作用是定义网页的样式 CSS样式 1. 行内样式 行内样式:直接定义在 HTML 标签的 style 属性中 <!DOCTYPE html> <html la…

文件读取和写入

1、with open 和 open close 的对比 with open 的优点 1、自动关闭文件&#xff1a;with 语句会在代码块执行完毕后自动关闭文件&#xff0c;无需显式调用 close() 方法。 2、异常安全&#xff1a;如果在代码块中发生异常&#xff0c;with 语句仍然会确保文件被正确关闭。 3、…

编译器的学习

常用的编译器&#xff1a; GCCVisual CClang&#xff08;LLVM&#xff09;&#xff1a; Clang 可以被看作是建立在 LLVM 之上的一个项目, 实际上LLVM是clang的后端&#xff0c;clang作为前端前端生成LLVM IR&#xff0c;https://zhuanlan.zhihu.com/p/656699711MSVC &#xff…

轻量和ECS对比:阿里云轻量应用服务器和云服务器有啥区别?

阿里云轻量应用服务器和云服务器ECS区别对照表&#xff0c;一看就懂的适用人群、使用场景、优缺点、使用限制、计费方式、网路和镜像系统全方位对比&#xff0c;阿里云服务器网aliyunfuwuqi.com整理ECS和轻量应用服务器区别对照表&#xff0c;可以在阿里云CLUB中心领取 aliyun.…

【银角大王——Django课程——ORM】

Django课程——ORM框架 Django 模型使用自带的 ORMORM 解析过程:ORM 对应关系表&#xff1a;下载mysqlclient安装包创建数据库——ORM只能操作表&#xff0c;无法创建数据库。连接数据库——修改settings中的DATABASESDjango操作表&#xff0c;在models.py文件中编写——操作表…

CPP语法(六)——函数模板

CPP语法 六—函数模板 一、 模板1.1 函数模板1.2 重载函数模板1.3 类模板1.3.1 简单类模板1.3.2 默认模板参数1.3.3 为具体类型的参数提供默认值1.3.4 有界数组模板 1.4 模板的使用1.4.1 定制模板类1.4.2 定制类模板成员函数 一、 模板 模板是c的高级特性&#xff0c;分为函数…