1.类和对象的基本概念
1.c语言与c++中的结构体
我们知道在c语言里,我们是无法在结构体内部定义函数的,但在c++里,我们可以定义函数。从这里我们就可以看出c++对于数据(属性)和行为(方法)是封装的。它可以在数据的储存里同时添加了数据操作的功能。
所谓封装就是将抽象得到的数据和行为相结合,形成一个有机体,及就是将数据与操作数据的函数代码进行有机的结合,形成类,其中的数据和函数都是类的成员。
c语言中结构体中不能存放函数,也就是数据(属性)和行为(方
法)是分离的
c++中结构体中是可以存放函数的,也就是数据(属性)和行为
(方法)是封装在一起的。
所以了解c++中的类是至关重要的。
2.类的封装性
c++将事物的属性和行为封装在一起
类和结构体的一个区别在于,类对成员可以进行访问的权限控
制,结构体不可以
类 = 类型 (事物的行为和属性) 类实例化出来的变量叫对象
类中的函数 可以访问类里面的成员
类将具有共性的数据和方法封装在一起,加以权限区分,用户只能通过公共的方法访问私有数据。
类的权限分为:private (私有) ,public (公有), protected(保护)三种权限。
这些权限是针对类外部的访问,只有公有(public)数据才能被访问,在没有涉及到继承与派生是,private和protected是同等级的,外部都不允许访问,要想访问到该成员,只能通过公有的方式间接访问到这两类数据。
3.定义类
类的关键字 class ,类的定义方式为:
class 类名
{
成员列表
}
c++中对事物的封装 将属性和行为封装在一起
类 将事物抽象成属性和行为,并且封装在一起
类中定义的成员不声明权限,默认为私有型。
举个例子:
/定义一个类 class Data { private: int a;//私有数据 也是默认的类型 protected: int b;//保护数据 public: int c;//公有数据 void showdata()//方法 { cout << a << " " << b << " " << c << endl; } }; //使用类 int main() { //定义Data类的一个对象 Data data; //只能访问公有的数据 cout << data.c<<endl; //通过公有的方法实现间接访问私有的数据 data.showdata(); //打印data中的a,b,c。 }
结构体中所有成员默认都是公有的 而类中的所有成员默认是私有的,且在结构体中也可以修改成员的访问权限。
设计一个类需要我们对该类的方法与数据做出详细的判断,比如设计一个人的类
class person { private: char pname[20]; int page; char pIDnumber[10]; public: void Initperson(char* name,int age, char *IDnumber)//初始化person { strcpy(pname, name); if (age > 0) { page = age; } else { cout << "错误格式" << endl; } strcpy(pIDnumber, IDnumber); } //修改名字 void setname(char *arr) { strcpy(pname, arr); } //修改年龄 void setage(int age) { if (age > 0) page = age; } //修改身份号码 void setIDnumber(char* arr) { strcpy(pIDnumber, arr); } //打印信息 void showperson() { cout << "姓名:" << pname << endl; cout << "年龄:" << page << endl; cout << "身份号码:" << pIDnumber << endl; } }; int main() { //定义两个person类的对象 person jack; //初始化 jack.Initperson((char*)"jack", 12,(char *)"123456"); jack.setage(18); jack.showperson(); return 0; }
尽量设置成员变量为私有权限
设置成员变量为私有,优点:
对变量的设置时的控制
可以给变量设置只读权限
可以给变量设置只写权限
可以给变量设置可读可写权限
当然我们也可以类外实现方法-即函数,不过我们需要添加作用域符来表明所属地。
class Data { private: int a;//私有数据 protected: int b;//保护数据 public: int c;//公有数据 void showdata()//方法 { cout << a << " " << b << " " << c << endl; } void getA(int a); }; void Data::getA(int A) { a = A; }
4.构造与析构
构造与析构的概念:
创建对象时,对对象进行初始化的工作,就是构造
销毁对象时对对象进行清理工作,就是析构
一般需要人为提供,如果不提供,那么编译器也会给提供,只是编译器提供的构造和析构函数不会做任何操作,只是默认为空。若创建有构造函数与析构函数,编译器会自动调用构造函数与析构函数。
创建对象时和释放对象时,构造函数和析构函数自动会调用,不 需要人为调用。
构造函数的特点:
1.没有返回值
2.没有函数返回类型
3.函数名与类名一样
4.可以发送函数重载
5.创建对象时,会自动调用。
析构函数的特点:
没有返回值
1.函数名: 类名前面加上~
2.没有参数
3.不能发送函数的重载
4.销毁对象之前,回被自动调用
构造函数
构造函数的几种方式:
class Data { private: int a;//私有数据 protected: int b;//保护数据 public: Data()//无参构造函数 { c= 0; } int c;//公有数据 Data(int x,int y)//有参构造函数 { c = x; a=y; } }; int main() { //隐式调用无参构造函数(未创建构造函数,构造函数默认为无参的) Data b1; //显示调用无参构造函数 Data b2=Data(); //隐式调用有参构造函数 Data b3(1,2); //显式调用有参构造函数 Data b4 = Data(1,2); //匿名对象(无名构造对象) 存活周期为当前语句结束,立即释放 Data(); Data(20,10); //构造函数隐式转换(类中只有一个数据成员) Data b5 = 100; }
构造函数的分类
无参构造和有参构造
普通沟通和拷贝构造
拷贝构造函数的写法: 类名 ( const 类名 & obj ){}
注意:
如果自定义了一个构造函数,系统将不再提供默认的构造函数.
如果自定义了一个拷贝构造,系统将不再提供默认的拷贝构造.
默认的拷贝构造是简单的值拷贝.
如果创建对象时,不能调用对应的构造函数,将不能创建出对象.
我们要习惯去在构建类时,把构造函数也构建了。
析构函数
函数名称与类名相同,在函数名前加~,没有返回类型,没有函数形参,不能被重载。
当对象生命周期结束时,系统自动调用析构函数。
先调用析构函数,在释放对象空间。
析构函数的定义
class Data1 { private: int a;//私有数据 protected: int b;//保护数据 public: Data1(int x)//有参构造函数 { c= x; cout << "构造函数:" << c << endl; } int c; ~Data1()//析构函数 { cout<<"析构函数:"<<c<<endl; } }; Data1 b1(10);//整个项目结束时才会析构 void test1() { Data1 b2(20); { Data1 b3(30);//局部对象 (出了范围就会自动调用析构函数销毁) } Data1 b4(40); } int main() { test1(); return 0; }
运行来通过打印顺序发现函数调用顺序:
一般析构函数为空,这里只是展示一下调用关系才写了打印功能。
一般不写析构函数,但若存指针,必须要写析构函数,因为所在堆区空间,默认是无法释放的,会造成内存泄漏,我们要创建析构函数释放这一部分空间。
拷贝构造函数
拷贝构造:本质是构造函数
拷贝构造函数的写法:
类名(const 类名 &obj){}
拷贝构造函数的调用时机
总结一种情况: 旧对象初始化新对象
分类:
旧对象初始化新对象
形参是一个对象
返回局部对象
c++默认增加的函数
默认情况下, c++ 编译器至少为我们写的类增加 3 个函数
1 .默认构造函数 ( 无参,函数体为空 )
2 .默认析构函数 ( 无参,函数体为空 )
3 .默认拷贝构造函数,对类中非静态成员属性简单值拷贝
如果用户定义拷贝构造函数, c++ 不会再提供任何默认构造函数
如果用户定义了普通构造 ( 非拷贝 ) , c++ 不在提供默认无参构造,但是
会提供默认拷贝构造.
类对象成为另一个类的成员
类中有多个对象时,构造的顺序是先构造里面的对象,在构造外
面的对象.
类中有多个对象时,析构时顺序是先析构外面的对象,在析构里
面的对象.