类成员的三种访问权限
1、private代表类内私有成员,仅有类内函数可以访问private,类外一切函数(包括继承者)均不可访问private成员。
2、public代表类内公有成员,无论类内还是类外(包括继承者)的函数都可以访问public成员。
3、protect(即保护成员),主要用在类的继承中。如果有任何变量或函数被声明为protect,那么这些保护成员可以被类的继承者中成员函数访问,而无法被类外任何函数访问。
注意类中默认的访问权限时private 而结构体中默认的访问权限时public
对象,成员函数的几种定义方式
class Test{
int a;
char b;
int add(int x,int y);
};
Test t;//这里定义了一个Test的对象 t
t.a=1;//存取成员变量
Test*pt=new Test;//定义了一个Test类型的指针
pt->a=10;//存取成员变量
对于成员函数的几种定义方式:
1、在类内定义:(不推荐)
这样会使得类给非常臃肿 不方便代码的阅读 非常不清晰
2、类中声明,同文件类外定义
int Test::add(int x,int y)
{
return x+y;
}//这里的Test::是用来说明add属于Test类 ::是类的作用域分辨符
3、在其他文件定义
例如在test.h中定义了 Test类
然后在test.cpp中定义
#include"test.h"
int Test::add(int x,int y)
{
return x+y;
}
拷贝构造函数
拷贝构造函数时一种特殊的构造函数,c++提供的拷贝构造函数用于建立新对象时将已存在的对象的数据成员值复制给新对象,即用一个已经存在的对象初始化新建立的对象
类名(类名&对象名)
{
…
}
例如:
class time{
int h;
int m;
int s;
time(int H,int M,int S);
time(time&t2);
};
time::time(int H,int M,int S)
{
this->h=H;
this->M=m;
this->S=s;
}
time::time(time& t2)
{
this->h=t2.h;
this->M=t2.m;
this->S=t2.s;
}
time t1(1,2,3);
time t2(t1);
注意:当对象作为函数的返回值的时候,需要调用拷贝构造函数,此时c++从堆区中动态建立一个临时对象,将函数返回的对象复制给该临时对象,并且把该临时对象的地址储存到寄存器里,从而由该临时对象完成函数返回值的传递,多以我们返回的并不是你写在return 后面的那个对象 而是它的副本
深浅拷贝
浅拷贝:直接将原对象的数据成员值一赋给新对象中对应的数据成员
但是对于指针成员来说,简单的=赋值 只是把新对象中的指针指向了元对象指针成员所指的内存空间,并没有新开辟一块内存,所以当原对象和新对象析构的时候 同一块内存会被释放两次 所以程序会出现异常
深拷贝:当类的数据成员中有指针类型的时候,我们必须定义一个特殊的拷贝构造函数,不经可以实现原对象和新对象之间数据成员的复制,而且可以为新对象分配单独的内存资源
深拷贝示例:
class Test{
int a;
string str;
Test(Test&t);
}
Test::Test(Test&t)
{
this->a=t.a;
if(t.str.length()!=0)
{
this->str=new char[t.str.length()+1];
strcpy(this->str,t.str);
}
}
初始化列表
:https://blog.csdn.net/jolin678/article/details/128600596
静态成员
为了解决同一个类不同对象之间数据成员和函数的共享问题 c++提供了静态成员
类的静态成员分为两种 静态数据成员 静态函数成员
静态数据成员
在面向对象的方法中不同对象值不同的属性叫做实例属性
同一个类不同对象值相同的属性叫做类属性
C++就是用静态数据成员来实现类属性
类内声明静态数据成员的格式:
static 数据类型 静态数据成员名;
类外声明静态成员的格式:
数据类型类名::静态数据成员名=初始值;
注意:
1、静态数据成员的访问属性和普通数据成员一样 可以为public private protected
2、静态数据成员脱离具体对象而独立存在 其储存空间时独立分配的 不是任何对象储存空间的一部分
但逻辑上所有的对象都共享这一储存单元 所以对静态数据成员的任何操作都将影响共享这一储存单元的所有对象。
3、静态数据成员应该在类外某处进行初始化 而且它的初始化和访问权限无关
4、静态数据成员初始化的时候前面不用加static 防止和一般的静态变量混淆
5、静态数据成员时类的成员 所以在初始化的时候必须加上类的作用域运算符 类名:: 而且还要写数据类型 例如 int A :: a=10;
静态函数成员
静态成员函数可以在类内定义 和可以子啊内外定义 在类外定义的时候不能用static作为前缀
调用静态成员函数的两种格式
对象调用:对象名.静态成员函数
类调用:类名::静态成员函数
友元
友元函数
frend 返回值 函数名(;形参表);//友元函数的声明
可以在类中定义也可以在类外定义 友元函数不属于该类 所以类外定义的时候不能加上类的作用域说明符
友元函数可以访问类中的所有成员
调用友元函数的时候不能通过类来调用
友元类
friend 类名;
calss B;
class A{
friend B;
…
}
B所有的成员函数都是类A的友元函数
注意:友元关系不能传递
常对象和常成员
常对象
不允许修改的对象成为常对象
类型名 const 对象名 ; 或者 const 类型 对象名
c++规定只有类的常成员函数可以访问该类的长对象 当然const成员函数任然不可以修改长对象只能访问
const对象不能被赋值 所以必须在定义的时候有构造函数初始化
常成员
常数据成员:
前面用const修饰的数据成员就是常数据成员
const 数据类型 成员名 或者 数据类型 const 成员名
常数据成员必须进行初始化 并且不能被更新 但是常数据成员的初始化只能通过构造函数的初始化列表进行
常函数成员:
返回值类型 函数名 (形参表) const;//常函数成员的声明
注意:const 是函数类型的一部分 所以定义的时候也要带有const关键字
常成员函数不能更新成员数据 不能调用其他成员函数 是常对象唯一的对外接口
const关键字还可以用于重载函数的区分(常对象调用的是常成员函数 一般对象调用的是一般成员函数)
对象的内存分布
对象的内存空间的分配和一般的变量基本一样
1、对象的数据成员和函数成员占据不同的内存空间 数据成员的内存空间和对象的存储类别相关 成员函数的的内存空间在代码段中
2、一个类的所有对象的数据成员拥有各自的储存空间
3、一个类所有对象的成员函数为该类所有对象共享 在内存中只有一个副本
对象的内存空间的释放:
1、全局对象数据‘成员占有的内存空间在程序结束时释放
2、局部对象和实参对象数据成员的空间在函数调用结束时释放
3、动态对象数据成员的空间用delete释放
4、对象的成员函数的内存空间在该类所有对象的生命周期结束的时候自动释放