1.对于c++的封装,私有权限,这个权限只能在类里面去使用,不能在外面使用这个成员属性。
class person
{
private:
int age;
}
person p1;
p1.age = 10;
这个时候,你在外面栈上去使用这个成员属性,可以任意操作,那就不是私有的了,私有的意思是只有该对象有权限对这个属性就行操作。
2.static关键字:
用在成员属性上就是静态成员变量,成员方法那就是静态成员方法。
1.静态成员属性 是所有对象共同拥有一个,就是说类生成的所有的对象,只有一份数据。
2.静态成员函数:可以使用静态成员属性。
与一般的数据成员不同,无论建立了多少个对象,都只有一个静态数据的拷贝。静态成员变量,属于某个类,所有对象共享。
静态变量,是在编译阶段就分配空间,对象还没有创建时,就已经分配空间。
注意点:
- 静态成员变量必须在类中声明,在类外定义。
- 静态数据成员不属于某个对象,在为对象分配空间中不包括静态成员所占空间。
3.静态数据成员可以通过类名或者对象名来引用。
3.静态成员函数:
在类定义中,前面有static说明的成员函数称为静态成员函数。静态成员函数使用方式和静态变量一样,同样在对象没有创建前,即可通过类名调用。静态成员函数主要为了访问静态变量,但是,不能访问普通成员变量,静态成员函数的意义,不在于信息共享,数据沟通,而在于管理静态数据成员,完成对静态数据成员的封装。
- 静态成员函数只能访问静态变量,不能访问普通成员变量
- 静态成员函数的使用和静态成员变量一样
- 静态成员函数也有访问权限
- 普通成员函数可访问静态成员变量、也可以访问非静态成员变量
#include<iostream>
#include<string>
using namespace std;
class person
{
public:
person()
{
cout <<"默认构造函数"<<endl;
};
person(int age)
{
cout<<"有参构造函数"<<endl;
m_age = age;
}
static void fun()
{
cout <<m_age<<endl; //访问静态成员变量
//cout <<num<<endl;不可访问非静态成员变量
}
static int m_age; //类内声明 静态成员变量是有权限控制的.私有和公共
private:
static int m_year;
static void func2()
{
cout <<m_age<<endl;
}
};
int person::m_age = 20; //类外初始化和定义
int person::m_year = 200;
int main(void)
{
cout<<"main 函数"<<endl;
person p1;
person p2 ;
p2.fun();
person::fun();
p2.m_age = 400; //修改为400,类所有的对象都为400
cout <<person::m_age<<endl; //也可以通过类名访问
//cout <<person::m_year<<endl; 私有权限不可访问
return 0;
}
4.设计模式:单例模式(利用的就是静态成员变量和静态成员函数的属性来实现的)
1>示例一:主席案例
#include<iostream>
#include<string>
using namespace std;
//为了只能创建一个主席对象,需要将所有的构造函数以及静态成员变量都放在私有属性里面
//因为为了不允许外界去创建对象,只能通过类名区获取对象
//而且因为外界不能创建对象,那么只能通过类自己本身区创建自己的对象.
class chairman
{
public:
static chairman* getinstance() //必须为静态成员函数,才可以对静态成员变量进行操作.
{
return chair;
}
void set_name(string name)
{
this->name = name;
}
void set_age(int age)
{
this->age = age;
}
string get_name()
{
return this->name;
}
int get_age()
{
return this->age;
}
private:
static chairman *chair;
string name;
int age;
chairman()
{
}
chairman(string name,int age)
{
this->name = name;
this->age = age;
}
chairman(const chairman &c)
{
this->name = c.name;
this->age = c.age;
}
};
chairman * chairman::chair = new chairman; //为什么可以这样做,其实编译器就是将这句话放到类里面去执行了,而且在编译阶段,静态成员变量就已经生成了.
int main(void)
{
chairman *c1 = chairman::getinstance();
chairman *c2 = chairman::getinstance();
if(c1==c2)
{
cout<<"二者是一样的"<<endl;
}
return 0;
}
对于这个案例单例模式,可以这么理解:
1.为了外部不能在创建对象,所有所有的构造函数都必须放在私有属性里面;
2.为了只能创建一个对象,所有通过静态成员变量来实现的,初始化和定义在类外,类外调用了类的构造函数,因为对于编译器而言,最终这段代码还是放在类内实现的,所以这样写是可以的,同时我们必须提供一个静态成员函数去供外部获得这个静态成员变量。
3.所有的对象的属性和方法剩下和普通的类和对象创建是一样的。
2>示例二:打印机
打印机的代码和主席案例代码是类似和一样的。
如果一个类的成员,既要实现共享,又要实现不可改变,那就用 static const 修饰。定义静态const数据成员时,最好在类内部初始化。
5.对象内存分区:
class Person
{
public:
int m_A; //非静态成员变量,属于对象身上
void func( ) {}; //非静态成员函数 不属于对象身上
static int m_B; //静态成员变量 ,不属于对象身上
static void func2(){}; //静态成员函数 ,不属于对象身上
double m_C; // 12 错误 16正确
};
//结论 : 非静态成员变量 ,才属于对象身上
this指针,this指针永远指向当前对象。成员函数通过this指针即可知道操作的是那个对象的数据。This指针是一种隐含指针,它隐含于每个类的非静态成员函数中。静态成员函数内部没有this指针,静态成员函数不能操作非静态成员变量。
空类的大小为 1 每个实例的对象 都有独一无二的地址,char维护这个地址。 一个空类,他的内存大小为1 。
5.常函数:
首先举一个简单的例子:
#include<iostream>
#include<string>
using namespace std;
class person
{
public:
void func()
{
cout <<"hello world"<<endl;
}
void func1()
{
if(NULL == this)
{
return;
}
cout <<this->age<<endl;
}
int age;
};
int main(void)
{
person *p = NULL;
p->func(); //这样是可以的,因为成员函数没有使用到this指针
//p->fun1(); 这样是错误的,因为成员函数使用到了this指针而这个this指针是个空指针,所以报错.
p->func1();//当他加上那个判断this是否为空,就可以通过了.
return 0;
}
常对象和常函数,示例代码:
#include<iostream>
#include<string>
using namespace std;
class person
{
public:
person()
{
this->m_a = 10;
this->m_b = 20;
}
void func()
{
cout <<"hello world"<<endl;
}
void show() const //加了const,成员函数就变成了常函数,不可以修改指针指向的值.
{
m_B = 1000;
cout <<this->m_a<<endl;
cout <<m_b<<endl;
}
int m_a;
int m_b;
mutable int m_B; //就算是常函数 我还是执意要修改
};
int main(void)
{
person p1;
p1.show();
const person p2;
//p2.func(); //加了const之后,对象变成常对象,不可以调用普通成员函数,可以调用常函数
//p2.m_b = 20;常对象 不允许修改属性
p2.show();
return 0;
}
6.友元函数,友元类,友元成员函数:
1>全局函数作为友元函数:就是全局函数可以访问类的私有属性
示例代码:
#include<iostream>
#include<string>
#include<string>
using namespace std;
class building
{
friend void goodGay( building * building ); //加上这句话,全局函数就变为友元函数了。
public:
building()
{
m_sittingroom="客厅";
m_bedroom = "卧室";
}
string m_sittingroom;
private:
string m_bedroom;
};
//全局函数 好基友
void goodGay( building * building )
{
cout << "好基友正在访问 " << building->m_sittingroom << endl;
cout << "好基友正在访问 " << building->m_bedroom << endl;
}
int main(void)
{
building* build = new building;
goodGay(build);
return 0;
}
2>类作为友元类,一个类作为另一个类的友元类
示例代码
#include<iostream>
#include<string>
using namespace std;
class building;
class goodgay
{
public:
goodgay();
void vist();
private:
building *build;
};
class building
{
friend class goodgay; //加上这句就是友元类
public:
building()
{
m_sittingroom="客厅";
m_bedroom = "卧室";
}
string m_sittingroom;
private:
string m_bedroom;
};
//这两句话必须放class building 定义的后面,否则会报错.
//因为classA的func函数使用了B的成员,所以必须在使用之前知道B的定义细节。
//参考博客:https://blog.csdn.net/xiaojun111111/article/details/94620944
//你可以把A的func延后实现(只在classA中定义func)。
goodgay::goodgay()
{
build = new building;
}
void goodgay::vist()
{
cout <<"基友拜访" <<this->build->m_sittingroom<<endl;
cout <<"基友拜访 "<<this->build->m_bedroom<<endl;
}
int main(void)
{
goodgay gg;
gg.vist();
return 0;
}
3>成员函数作为友元
示例代码:
#include<iostream>
#include<string>
using namespace std;
class building;
class goodgay
{
public:
goodgay();
void vist();
private:
building *build;
};
class building
{
friend void goodgay::vist(); //成员函数作为友元
public:
building()
{
m_sittingroom="客厅";
m_bedroom = "卧室";
}
string m_sittingroom;
private:
string m_bedroom;
};
goodgay::goodgay()
{
build = new building;
}
void goodgay::vist()
{
cout <<"基友拜访" <<this->build->m_sittingroom<<endl;
cout <<"基友拜访 "<<this->build->m_bedroom<<endl;
}
int main(void)
{
goodgay gg;
gg.vist();
return 0;
}