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.mzph.cn/diannao/2285.shtml

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

相关文章

Jammy@Jetson Orin - Tensorflow Keras Get Started: 000 setup for tutorial

JammyJetson Orin - Tensorflow & Keras Get Started: 000 setup for tutorial 1. 源由2. 搭建环境2.1 安装IDE环境2.2 安装numpy2.3 安装keras2.4 安装JAX2.5 安装tensorflow2.6 安装PyTorch2.7 安装nbdiff 3. 测试DEMO3.1 numpy版本兼容问题3.2 karas API - model.compil…

B008-方法参数传递可变参数工具类

目录 方法参数传递可变参数冒泡排序Arrays工具类Arrays工具类常用方法 方法参数传递 /*** java中只有值传递* 基本数据类型 传递的是具体的值* 引用数据类型 传递的是地址值*/ public class _01_ParamPass {public static void main(String[] args) {// 调用方法 getSumge…

爱普生计时设备AUTOMOTIVE RA8900CE DTCXO RTC

主要特点出场已校准带有DTCXO的RTC&#xff0c;并且内部集成晶体单元高精度: 3.4 ppm 40 to 85 C(9 s/月.)时钟输出:1 Hz.1024 Hz.32.768 kHzI 2 C Interface: Fast mode (400 kHz)The l2C-Bus is a trademark ofNXP Semiconductors供电电压: 2.5-5.5 V(main),1.6-5.5 V(备份电…

学习springcloud中Nacos笔记

一、springcloud版本对应 版本信息可以参考&#xff1a;版本说明 alibaba/spring-cloud-alibaba Wiki GitHub 这里说2022.x 分支对应springboot的版本信息&#xff1a; Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version 2022.0.0.0* Spring Cloud 202…

IO进程(进程间通信IPC)

进程间通讯 IPC InterProcess Communication 1.进程间通信方式 1.早期进程间通信&#xff1a; 无名管道(pipe)、有名管道(fifo)、信号(signal) 2.system V IPC&#xff1a; 共享内存(shared memory)、消息队列(message queue)、信号灯集(semaphore set) 3.BSD&#xff1a; 套接…

js的算法-交换排序(快速排序)

快速排序 基本思想 快速排序的基本思想是基于分治法的&#xff1a;在待排序表L【1...n】中任意取一个元素p 作为枢轴&#xff08;或基准&#xff0c;通常取首元素&#xff09;。通过一趟排序将待排序表划分为独立的两部分L【1...k-1】和L【k1...n】;这样的话&#xff0c;L【1…

笔试题1 -- 吃掉字符串中相邻的相同字符(点击消除_牛客网)

吃掉字符串中相邻的相同字符 文章目录 吃掉字符串中相邻的相同字符题目重现解法一&#xff1a;(基于 erase() 函数实现)解法二&#xff1a;&#xff08;利用 栈 辅助实现&#xff09;总结 题目链接&#xff1a; 点击消除_牛客网 题目重现 牛牛拿到了一个字符串。 他每次“点击…

(数据结构代码,总结,自我思考)=> { return 个人学习笔记; } 【To be continued~】

俗话说 “学而不思则罔”&#xff0c;是时候复习和整理一下自己先前的学习历程了&#xff01; Chapter-One 《BinarySearch》 public static int binarySearch (int[] a, int target) {int i 0, j a.length - 1;while (i < j) {int m (i j) >>> 1; // 求中位…

jsp实验10 JavaBean

二、实验项目内容&#xff08;实验题目&#xff09; 编写代码&#xff0c;掌握javabean的用法。【参考课本 上机实验 5.5.1 】 三、源代码以及执行结果截图&#xff1a; 源代码&#xff1a; Fraction.java package sea.water; public class Fraction { public double numbe…

类和对象(2)——封装(封装的概念、包、staic)

前言 面向对象程序三大特性&#xff1a;封装、继承、多态。而类和对象阶段&#xff0c;主要研究的就是封装特性。何为封装呢&#xff1f;简单来说就是套壳屏蔽细节。 一、什么是封装 1.1 概念 将数据和操作数据的方法进行有机结合&#xff0c;隐藏对象的属性和实现细节&…

零元购与消费增值:电商新商业模式的探索与实践

大家好&#xff0c;我是微三云周丽&#xff0c;今天给大家分析当下市场比较火爆的商业模式&#xff01; 小编今天跟大伙们分享什么是零元购与消费增值模式&#xff1f; 在数字化浪潮的推动下&#xff0c;电商行业正经历着qian所未有的变革。传统的ying销ce略逐渐失去效力&…

有关栈的练习

栈练习1 给定一个栈&#xff08;初始为空&#xff0c;元素类型为整数&#xff0c;且小于等于 109&#xff09;&#xff0c;只有两个操作&#xff1a;入栈和出栈。先给出这些操作&#xff0c;请输出最终栈的栈顶元素。 操作解释&#xff1a; 1 表示将一个数据元素入栈&#xff…

书生浦语训练营第2期-第5节作业

一、基础作业 1.1 LMDeploy环境部署 &#xff08;1&#xff09;创建conda环境 studio-conda -t lmdeploy -o pytorch-2.1.2 &#xff08;2&#xff09;安装Lmdeploy 激活刚刚创建的虚拟环境。 conda activate lmdeploy 安装0.3.0版本的lmdeploy。 pip install lmdeploy[all]0…

达梦(DM)数据库表索引

达梦DM数据库表索引 表索引索引准则其他准则 创建索引显式地创建索引其他创建索引语句 使用索引重建索引删除索引 表索引 达梦数据库表索引相关内容比较多&#xff0c;常用的可能也就固定的一些&#xff0c;这里主要说一下常用的索引&#xff0c;从物理存储角度进行分类&#…

在线测径仪的六类测头组合形式!哪种适合你?

在线测径仪&#xff0c;这一现代工业的精密仪器&#xff0c;犹如一位技艺高超的工匠&#xff0c;以其卓越的性能和精准度&#xff0c;为工业生产提供了坚实的保障。它的出现&#xff0c;不仅提高了生产效率&#xff0c;更保证了产品质量&#xff0c;为企业的可持续发展注入了强…

基于JavaWeb开发的springboot网约车智能接单规划小程序[附源码]

基于JavaWeb开发的springboot网约车智能接单规划小程序[附源码] &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种…

SLICEM是如何将查找表配置为分布式RAM/移位寄存器的

1.首先说SliceM和SliceL如何配置为ROM的 一个SLICE包含4个六输入查找表&#xff0c;因此每个查找表就能存储64bit的数据&#xff0c;要实现128bit的ROM&#xff0c;只需要通过两个LUT就可实现&#xff0c;具体如下表: 2.如何配置成为分布式RAM SLICEM中的LUT如下图&#xff…

Excel模板导入、导出工具类

1.引入maven依赖&#xff0c;利用hutool的excel读取 Hutool-poi对excel读取、写入 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency> <depen…

Linux之安装Nginx

目录 传送门前言一、快速安装二、反向代理语法1、基本语法2、location语法1. 基本语法2. 匹配规则3. 修饰符4. 权重5. 嵌套location6. 其他指令7.案例 三、配置反向代理 传送门 SpringMVC的源码解析&#xff08;精品&#xff09; Spring6的源码解析&#xff08;精品&#xff0…

Java 海报-基于Graphics2D 实现个人头像的圆形裁剪

效果&#xff1a; 代码&#xff1a; private static BufferedImage resizeAndClipToCircle(BufferedImage image, int size) {// 缩小图片BufferedImage resizedImage new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);Graphics2D g2d resizedImage.createGraphi…