前言
本文章根据王立柱版《C/C++与数据结构》学习几种类以及模板的使用进行知识点总结。
C++知识点复习
一、顺序表类
总代码如下:(知识点包括在其中)
typedef int Type;//将Type定义为int型,利用typedef方便之后进行数据类型的修改
#include<iostream>
using namespace std;
/*C++顺序表类:
1.new与delete是根据C中malloc和free改进而来
2.有自动调用的构造函数和析构函数
3.有调用权限差别
4.有运算符重载函数(返回引用型)*/
class SeqList
{
private://注意私有成员,调用此中间的数据需要在public中定义专门调用私有成员的函数,以防权限问题。(protected也是一样)
Type* data;//储存数据
int size;//数据个数
int max;//最大容量
void Error(const char* s)const {
cout << s; exit(1); }//错误信息的报告,exit(1)是一个出口,表示一场退出;exit(0)表示正常退出
public:
//复制构造函数
SeqList(int n = 100);//默认参数只在函数声明中出现,当有多个形参时,必须遵从从右向左连续列出各个参数的默认值。
//转换构造函数
SeqList(const SeqList& l);
//析构函数
~SeqList() {
delete[]data; }
//赋值运算符重载
SeqList& operator=(const SeqList& l);
//尾插函数
void InsertRear(const Type& item);
//定点插入
void Insert(Type* itr,const Type& item);
//删除指定位置的数据
void Erase(Type* itr);
//清空顺序表
void Clear() {
size = 0; }//直接让数据个数为零就清空了顺序表
//下标运算符重载
Type& operator[](int id);
//供常成员函数调用的下表运算符
const Type& operator[](int id)const;
//读取size的函数
int Size()const {
return size; }
//判断顺序表是否为空
int Empty()const {
return size == 0; }
//判断顺序表是否已经满了
int Full()const {
return size == max; }
//读取顺序表首元素
Type* Begin() {
return data; }
//常成员读取
const Type* Begin()const {
return data; }
//读取顺序表尾元素
Type* End() {
return data + size; }
//常量调用
const Type* End()const {
return data + size; }
};
//默认构造函数如果data没有指向一个分配的空间,还要使用就会报错
SeqList::SeqList(int n)
{
data = new Type[n];
if (data == NULL)
Error("Memory allocation error\n");
size = 0;
max=n;
}
//引用传参减少了中间调用的复制构造函数造成的时间复杂度的影响
SeqList::SeqList(const SeqList& l)
{
data = new Type[l.max];
if (data == NULL)
Error("Memory allocation error\n");
size = l.size;
max = l.max;
}
//引用传参
void SeqList::InsertRear(const Type& item)
{
if (size == max)
Error("InsertRear:list is full!\n");
data[size] = item;
size++;
}
//赋值运算符重载,可以进行连续赋值,因此需要引用返回值
SeqList& SeqList::operator=(const SeqList& l)
{
if (max != l.max)
{
delete[]data;
data = new Type[l.max];
if (data == NULL)
Error("Memory allocation error!\n");
}
for (int i = 0; i < l.size; i++)
data[i] = l.data[i];
size = l.size;
max = l.max;
return *this;
}
//将指定位置的数据向后移,然后放入要插入的数据,如果顺序表已经满了的话就会有报错就不会进行以下操作了
void SeqList::Insert(Type* itr, const Type& item)
{
for (Type* p = data + size, *q = data + size - 1; p != itr; --p, --q)
*p = *q;
*itr = item;
size++;
}
//覆盖删除,即将指定位置的数据后向前移动覆盖前面的数据
void SeqList::Erase(Type* itr)
{
for (Type* p = itr,*q = itr + 1; q != data + size; ++p, ++q)
*p = *q;
size--;
}
//下标可以改动,所以需要用引用返回值
Type& SeqList::operator[](int id)
{
if (id<0 || id>size - 1)
Error("id is illegal!\n");
return data[id];
}
//常变量的下标不可以改变,第一个const作为常成员调用的标识,第二个表示这是一个常函数,不可以改变它中间的数据
const Type& SeqList::operator[](int id)const
{
if (id<0 || id>size - 1)
Error("id id illegal!\n");
return data[id];
}
void display_seqlist(Type* first, Type* last);
int main()
{
SeqList L;
L.InsertRear(5);
L.InsertRear(15);
L.InsertRear(20);
Type* p = L.Begin();
L.Insert(++p, 10);
display_seqlist(L.Begin(), L.End());
L.Clear();
return 0;
}
void display_seqlist(Type* first, Type* last)
{
for (; first != last; ++first)
cout << *first << '\t';
cout << endl;
}
小知识点复习总结:
1.malloc:
C语言中使用,头文件是<stdlib.h>
格式形如p=(int )malloc(100sizeof(int))//p指针指向开辟的100个int类型的空间
2.free:
C语言中使用,头文件是<stdlib.h>
格式形如free(data)//释放data数组的空间
3.new:
C++中使用,new是iostream中的关键字,因此不需要头文件
使用格式:
int *p=new int//给指针p开辟一个int型空间
int *p=new int(2)//给指针p开辟一个int型空间,并存放初始值为2
int *p=new int[]//开辟一个一维数组,[]内的值即为开辟数组的大小
int *p=new int[][]//开辟二维数组,其它与一维数组相同
4.delete:
C++中使用,delete是iostream中的关键字,因此不需要头文件
使用格式:
delete[]data//释放掉data数组的空间
malloc和free搭配使用,new与delete搭配使用,将使用过的内存空间释放出来再利用
5.构造函数与析构函数
一般来说编译器有自带的构造函数与析构函数,但是函数体都是空,不做任何作用。如果对构造函数有需求,需要手动定义自己所需求的构造函数,然后根据调用格式编译器会自动调用相应的构造函数。析构函数里面需要手动delete掉new开辟的空间。
6.运算符重载
成员函数运算符(.)、成员指针运算符(->)、域解析运算符(::)
不能创建运算符,赋值运算符(=)只能做成员函数重载,输入输出运算符(>>、<<)只能做全局函数重载
运算符重载形参列表中至少有一个要是自己定义的类型
下面重复的知识点就不进行一一说明啦 ( > < )
二、String类
String.h:
#include<iostream>
#include<cstdlib>
#include<string.h>
using namespace std;
class String {
private:
char* str;
int size;
void Error(const char* c)const;
public:
String(const char* c = "");
String(const String& s);
~String() {
};
//都是返回的引用类型
String& operator=(const char* c);
String& operator=(const String& s);
//指定位置插入
String& Insert(int id, const String& s);
//指定位置删除
String& Erase(int id, int num);
//求子串
String SubStr(int id, int num)const;
//串连接:类串=类串+类串
String operator+(const String& s)const;
//串连接:类串+C串
String operator+(const char *c)const;
//友元函数
friend String operator+(const char* c, const String& s);
bool operator==(const String& s)const;
bool operator==(const char* c)const;
friend bool operator==(const char* c, const String& s);
//强制类型转换
operator char* ()const;
//下标运算符重载
char& operator[](int id);
const char& operator[](int id)const;
//求串长
int Size(void)const {
return size; };
//字符查找
int Find_First_of(char ch, int id)const;
//子串查找
int Find_First_of(const String& s, int id)const;
//输入输出
friend istream& operator>>(istream& istr, String& s);
friend ostream& operator<<(ostream& ostr, const String& cs);
//串读取
int ReadString(istream& istr, char delimiter);
};
String::String(const char* c)//默认构造函数
{
size = strlen(c);
str = new char[size + 1];
if (str == NULL)
Error("String:overflow!");
strcpy(str, c);
}
String::String(const String& s)//复制构造函数
{
size = s.size;
str = new char[size + 1];
if (str == NULL)
Error("String:overflow!");
strcpy(str, s.str);
}
//返回的是指针,引用型的实质就是指针
String& String::operator=(