类和对象
1、类
是对一类事物的抽象,包括其属性(成员变量)和行为(成员函数)
定义一个类需要使用关键字 class,然后指定类的名称,类的主体是包含在一对花括号中,主体包含类的成员变量和
成员函数。
定义一个类,本质上是定义一个数据类型的蓝图,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些
操作。
2、对象
抽象类的实列化.
类提供了对象的蓝图,所以基本上,对象是根据类来创建的。声明类的对象,就像声明基本类型的变量一样。
3、oop(面向对象)思想特点
1、抽象
2、封装
3、分类
4、继承
5、多态
4、构造函数
对象生成的时候自动调用
名字和类名同名
默认构造(普通构造)、拷贝构造(深拷贝)、移动构造(浅拷贝)
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。
查看移动构造的效果,临时变量: -fno-elide-constructors 防止编译器优化 允许产生临时变量
4、析构函数
对象消亡自动调用。
类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带
有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
创建一个类系统会默认生成一些东西:默认构造,拷贝构造,析构,赋值符号,取地址符号
6、const成员变量
const成员需要使用初始化列表进行初始化
const成员函数,const修饰的成员函数不能存在修改成员变量的逻辑(包括引用返回)
非const函数可以调用const函数,const函数不能调用非const函数
7、 static
static修饰成员变量,不属于类,必须初始化
static修饰的成员函数,没有对象存在也能调用,
static修饰的成员函数,不能调用非static的成员函数,也不能访问非static的变量
非static修饰的成员函数,可以调用static修饰的成员函数,也可以访问static修饰的变量
所有对象共享一个static修饰的变量
8、友元函数
缺点: 破坏了封装,不安全,所以要慎用
优点: 效率高,一般是需要频繁访问类的成员变量时使用
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
有三种情况:
全局函数作为类的友元函数; 一个类作为另外一个类的友元类;一个类的成员函数作为另外一个类的友元函数
代码示例
封装一个顺序表的类 增 删 改 查 查看、使用static变量计算顺序表对象个数、友元函数实现查看功能·
/*===============================================
* 文件名称:seq.cpp
* 创 建 者:
* 创建日期:2023年09月05日
* 描 述:
================================================*/
#include <iostream>
#include <cstring>
using namespace std;
class seq
{
friend void show_seq(seq & s);
private:
int size;
static int len ;
string * data;
const int a;//const修饰的成员变量
public:
//构造函数(普通)
seq( int size = 16,int a = 0):a(a)
{
this->size = size ;
this->len = 0;
this->data = new string[this->size];
}
//拷贝构造
seq(seq & s):a(s.a)
{
this->size = s.size ;
len = 0;
data = new string[this->size];
strcpy(data,s->data);
}
//移动构造
seq(seq && s):a(s.a)
{
size = s.size;
len = 0;
data = s.data;
s.data =nullptr;
}
//析构函数🐶
~seq()
{
if( data != nullptr)
delete []data;
}
//增加
int add_seq(string str)
{
if( len == size )
return -1;
data[len] = str;
len++;
return 0;
}
//删除
int delete_seq(int index)
{
if( len > index )
{
string * p = data+index;
string * q = data+(len-1);
while( *p != * q )
{
*p = *(p+1);
p++;
}
len--;
}
else
{
return -1;
}
return 0;
}
//修改
int change_seq(int index , string str)
{
if( len > index )
{
data[index] = str;
}
else
{
return -1;
}
return 0 ;
}
//查找
string select_seq(int index)
{
if(len > index )
{
return data[index];
}
else
{
return "超过表长了";
}
}
//长度
int get_len()
{
return len;
}
};
//友元函数
void show_seq(seq & s)
{
for( int i = 0 ; i < seq::len ; i++ )
{
cout<<s.data[i]<<endl;
}
}
int seq:: len = 0 ;//static变量初始化
int main()
{
seq dog(32);
//增加
dog.add_seq("土狗");
//表长应为1
cout<<"表长:"<<dog.get_len()<<endl;
dog.add_seq("黑狗");
dog.add_seq("傻狗🐶");
dog.add_seq("小狗🐶");
dog.add_seq("二狗子🐶🐶");
//查询
cout<<"查询:下标为3的值:"<<dog.select_seq(3)<<endl<<endl;
//展示表内容
show_seq(dog);
//表长为5
cout<<"表长:"<<dog.get_len()<<endl<<endl;
//删除下标3
cout<<"删除下标3:"<<dog.delete_seq(3)<<endl;
//展示表内容
show_seq(dog);
//表长为
cout<<"表长:"<<dog.get_len()<<endl<<endl;
//修改下标2
cout<<"修改下标2:"<<dog.change_seq(2,"牛马")<<endl;
//展示表内容
show_seq(dog);
//表长为
cout<<"表长:"<<dog.get_len()<<endl;
}
结果