5.2对象的生存期
5.2.1静态生成期
对象的生存期与程序的运行期相同,则称它为静态生存期。
使用static修饰的变量;
静态局部变量特点,具有全局寿命,局部可见,只第一次进入函数时被初始化,
对全局变量和局部可见的解析:
指在该函数中,只第一次进入函数时被初始化;
在不同的函数中没有联系,
如在main中的a与在other中的a,没有关系;
唯一区别就是静态变量只在第一次进入函数时被初始化,后面再进函数就不会重新被初始化,用上次离开该函数时该变量的值。
5.3类的静态成员
静态成员是解决同一个类的不同对象之间数据和函数共享问题的;
5.3.1静态数据成员
1、定义
如果某个属性为整个类所共有,不属于任何一个具体的对象,则采用static来声明为静态成员;
静态成员在每一个类中只有一份,由该类中的所有对象共同维护和使用;
类:工厂;对象:产品;普通成员:生产产品的零件;静态成员:生产产品的机器,被所有的产品所共用;
2、访问
通过类名对它进行访问,
类名::标识符
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
//1.构造函数
Point(int xx ,int yy);
//2.复制构造函数
Point(Point &p);
//3.get返回私有属性
int getX(){ return x;}
int getY(){ return y;}
//4.析构函数
~Point() = default;
void show();
static int s; //在类中只能声明
private:
int x , y;
static int count; //静态变量声明
constexpr static int origin = 0;//常量静态成员类内初始化
};
//4.构造函数
Point::Point(int xx ,int yy):x(xx),y(yy){
count++;
}
//5.复制构造函数
Point::Point(Point &p){
x = p.x , y = p.y;
count++;
}
void Point::show(){
cout << "对象个数:"<<count << endl;
}
//6.静态数据成员定义和初始化,使用类名限定
int Point::count = 0; //私有
int Point::s = 3; //公有
int main()
{
Point a(4,5);
a.show();
Point b(a);
b.show();
cout << "公有静态成员s可通过类名::名称访问 " << Point::s << endl;
//cout << "count : " << Point::count << endl;私有成员不能访问,需要set and get
return 0;
}
对象个数:1
对象个数:2
公有静态成员s可通过类名::名称访问 3
5.3.2静态函数成员
同静态数据成员一样,为同一个类的所有对象所共有,通过类名或对象名来调用,
注意:静态成员函数可以直接访问该类中的静态变量和函数成员,但访问非静态成员,必须通过对象名来访问
class A{
public :
static void f(A a);
private:
int x; //非静态成员
static int y;
};
void A::f(A a){
cout << x;//错误
cout << a.x; //正确
cout << y; //正确
}
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
//1.构造函数
Point(int xx ,int yy);
//2.复制构造函数
Point(Point &p);
//3.get返回私有属性
int getX(){ return x;}
int getY(){ return y;}
//4.析构函数
~Point() = default;
static void show();
static int s; //在类中只能声明
private:
int x , y;
static int count; //静态变量声明
constexpr static int origin = 0;//常量静态成员类内初始化
};
//4.构造函数
Point::Point(int xx ,int yy):x(xx),y(yy){
count++;
}
//5.复制构造函数
Point::Point(Point &p){
x = p.x , y = p.y;
count++;
}
void Point::show(){
cout << "对象个数:"<<count << endl;
}
//6.静态数据成员定义和初始化,使用类名限定
int Point::count = 0; //私有
int Point::s = 3; //公有
int main()
{
Point a(4,5);
Point::show();
Point b(a);
Point::show();
return 0;
}
5.4类的友元
友元关系就是一个类主动声明哪些其他函数或类是它的朋友,进而给他们提供对本类的访问特许;
也就是说,通过友元关系,一个普通函数或类的成员函数可以访问封装于另一个类中的数据。
不用通过set and get 方法直接访问到私有变量。
在一个类中,可以利用关键字friend将其他函数或类声明为友元,
如果友元是一般函数或类的成员函数,则称为友元函数;
是一个类,称为友元类,友元类的所有成员函数自动成为友元函数
5.4.1友元函数
友元函数是在类中用关键字friend修饰的非成员函数,该函数不是本类中的成员函数,只是在该类中声明一下,声明该函数是本类的友元函数,
从而之后在该友元函数的函数体中可以通过对象名访问类的私有和保护成员;
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
//1.构造函数
Point(int xx ,int yy);
//2.get返回私有属性
int getX(){ return x;}
int getY(){ return y;}
// 3.声明友元函数
friend float dist(Point &p1 , Point &p2);
private:
int x , y;
};
//4.构造函数
Point::Point(int xx ,int yy):x(xx),y(yy){
}
//5.友元函数实现,这是一般函数,称为友元函数后,可以通过对象访问私有成员
float dist(Point &p1 , Point &p2){
double x = p1.x- p2.x;
double y = p1.y - p2.y;
return static_cast<float> (sqrt(x*x+y*y));
}
int main()
{
Point a(1,1) , b(4,5);
cout << "This distance is: ";
cout << dist(a , b);
return 0;
}
This distance is: 5
5.4.2友元类
若A类为B类的友元类,则A类的所有成员函数都是B类的友元函数,都可以访问B类的私有和保护成员。
class A{
public:
friend class B;
private:
int x;
};
class B{
public:
void set(int i);
private:
A a;
};
void B::set(int i){
a.x = i;//B是A的友元,所以在B的成员函数中可以访问A类对象的私有成员
}
5.5共享数据的保护
5.5.1常对象
常对象必须进行初始化,而且不能被更新,
const 类名 对象名;
5.5.2用const类成员
1、类成员函数
使用const修饰的函数为常成员函数,常成员函数声明的格式:
类名 函数名 ( ) const;
注意:
1)在类外定义实现成员函数时,也要带const 即函数头和声明一样;
2)如果一个对象是常对象,则该常对象只能调用它的常成员函数,而不能调用其他成员函数,
3)const可以用于对重载函数的区分,
class R{
public:
void print();
void print() const; //常成员函数
private:
int r;
}
void R::print() const{
cout << r;
}
2、常数据成员
常数据成员只能通过初始化列表来获得初值,
但当然也可以直接指定
#include <iostream>
using namespace std;
class A{
public:
A(int i);//构造函数
void show();
private:
const int a; //常数据成员
static const int b; //静态常数据成员
//也可以 static const int b = 10;
};
const int A::b = 10; //静态常数据成员在类外说明和初始化
//常数据成员只能通过初始化列表来获得初值
A::A(int i): a(i){
}
void A::show(){
cout << a << " : " << b << endl;
}
int main()
{
A a(100) , b(0);
a.show();
b.show();
return 0;
}
100 : 10
0 : 10
5.5.3常引用
在声明引用时用const修饰,被声明的引用就是常引用,常引用所引用的对象不能被更新。
const 类名 & 引用名;
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
//1.构造函数
Point(int xx ,int yy);
//2.get返回私有属性
int getX(){ return x;}
int getY(){ return y;}
// 3.声明友元函数
friend float dist(const Point &p1 , const Point &p2);
private:
int x , y;
};
//4.构造函数
Point::Point(int xx ,int yy):x(xx),y(yy){
}
//5.友元函数实现,这是一般函数,称为友元函数后,可以通过对象访问私有成员
float dist(const Point &p1 , const Point &p2){
double x = p1.x- p2.x;
double y = p1.y - p2.y;
return static_cast<float> (sqrt(x*x+y*y));
}
int main()
{
Point a(1,1) , b(4,5);
cout << "This distance is: ";
cout << dist(a , b);
return 0;
}
This distance is: 5