静态成员与友元
1. 静态成员
静态成员变量///静态成员函数
-
C++为什么需要静态成员
C语言中可以通过全局变量实现数据共享,在程序的任何位置都可以访问
C++中希望某个类的多个对象之间实现数据共享,可以通过static建立一个被局限在类中使用的全局资源,该类型资源被称为静态成员。
-
静态成员变量(可以理解为局限在类中使用的全局变量)
被static修饰的成员变量即为静态成员变量
class 类名{
static 数据类型 变量名;//声明
};
数据类型 类名::变量名 = 初值;//定义和初始化
实例化对象时只实现非静态成员变量
访问方式:
-
-
类名::静态成员变量;
-
对象.静态成员变量;
-
#include <iostream>
using namespace std;
class A
{
public:
int m_data;
static int s_data;
A(int data = 0)
{}
};
int A::s_data = 100;//定义并初始化
int main(void)
{
cout << A::s_data <<endl;
A a1(123);
cout << "a1 size = " << sizeof(a1) << endl;
cout << a1.s_data << endl;
A a2(1);
a2.s_data = 1234;
cout << a2.s_data << endl;
return 0;
}
-
静态成员函数
被static修饰的成员函数即为静态成员函数。
class 类名{
访问控制限定符:
static 返回类型 函数名(形参表) { ... }
};
注意:
-
静态成员函数可以直接定义在类的内部,也可以定义在类的外部,这一点和普通的成员函数没有区别。
-
静态成员函数没有this指针,没有const属性,可以把静态函数理解为被限制在类中使用的全局函数.
-
静态成员函数中只能访问静态成员,但是在非静态成员函数中既可以访问静态成员也可以访问非静态成员
-
静态成员函数和静态成员变量一样,也要受到类的访问控制限定符的约束
在类的外部访问静态成员函数
类名::静态成员函数(实参表);
对象.静态成员函数(实参表);
#include <iostream>
using namespace std;
class A{
public:
int m_data;
static int s_data;
A(int data=0):m_data(data){}
void func1(void){ // func1(A *this)
cout << m_data << endl;
cout << s_data << endl;
}
static void func2(){ //静态成员函数
cout << "静态成员函数" << endl;
cout << s_data << endl;
//cout << m_data << endl; //error
}
};
int A::s_data = 100; //定义 并 初始化
int main(void){
cout << A::s_data << endl;
A::func2();
//A::func1(); //func1(&对象的地址) error
return 0;
}
2.友元
类的封装具有信息隐藏能力,但也带来了访问效率的问题.c++通过友元给某些函数一项特权,可以访问类中的私有成员,使用的关键字是friend。
2.1 友元函数
友元函数可以直接访问类的私有成员
class X{
friend T f(...) ;// 声明f为X类的友元
...
};
T f(...){} //友元不是类的成员函数
#include <iostream>
#include <cmath>
using namespace std;
class point
{
private:
int x,y;
public:
point(int a = 20, int b = 49)
{
x = a;
y = b;
}
int getx()
{
return x;
}
int gety()
{
return y;
}
friend double dist2(const point&, const point&);//友元函数
};
double dist1(point& p1, point& p2)
{
double X = p2.getx() - p1.getx();
double Y = p2.gety() - p1.gety();
return sqrt(X*X + Y*Y);
}
double dist2(const point& p1, const point& p2)
{
double X = p2.x - p1.x;
double Y = p2.y - p1.y;
return sqrt(X*X + Y*Y);
}
int main(int argc, const char *argv[])
{
point p1(3, 6), p2(4, 8);
cout << dist1(p1, p2) << endl;
co ut << dist2(p1, p2) << endl;
return 0;
}
2.2 友元类
一个类可以是另一个类的友元,友元类的所有成员函数都是另一个类的友元函数,能够直接访问另一个类的所有成员。
#include <iostream>
using namespace std;
class A
{
private:
int x, y;
public:
A(int a, int b)
{
x = a;
y = b;
}
int getx()
{
return x;
}
int gety()
{
return y;
}
friend class B;
};
class B
{
private:
int z;
public:
B(int c = 0)
{
z = c;
}
int add(const A& a)
{
return a.x + a.y + z;
}
int sub(const A& a)
{
return a.x - a.y - z;
}
};
int main(int argc, const char *argv[])
{
A a(6,3);
B b(10);
cout << b.add(a) <<endl;
cout << b.sub(a) << endl;
return 0;
}
友元类不是双向的:B是A的友元类, 不意味着A也是B的友元类
2.3 友元成员函数
对一个类,可以指定它的某个成员函数是另一个类的友元,也就是友元成员函数。
3. 单例模式
单例模式(Singleton Pattern,也称为单件模式),使用最广泛的设计模式之一。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
面向对象编程中,每个对象都应该抽象代表一个设备,并通过对象完成对某个具体设备的管理和维护。
对于有些类只能有一个实例很重要,例如打印机管理器、设备管理器、任务管理器等。
实现单例模式的三个主要步骤:
-
私有化构造函数
class Singleton{ private: Singleton(void){...} Singleton(const Signleton &that){} ... };
-
使用静态成员变量维护唯一的单例对象
class Singleton{ private: Singleton(void){...} Singleton(const Signleton &that){} ... static Singleton s_instance; }; Singleton Singleton::s_instance;
-
定义静态成员函数用于获取单例对象
class Singleton{ private: Singleton(void){...} Singleton(const Signleton &that){} ... static Singleton s_instance; public: static Singleton& getInstance(void){ return s_instance; } }; Singleton Singleton::s_instance;
3.1 饿汉式
加载进程时即完成创建(饿), 用不用都创建。
#include <iostream>
using namespace std;
class Signleton
{
private:
int m_i;
Signleton(int i = 0)//构造函数
{
m_i = i;
}
Signleton(const Signleton& that){}//拷贝构造函数
static Signleton m_instance; //使用静态成员变量维护唯一的单例对象
public:
static Signleton& getInstance()
{
return m_instance;
}
void printf()
{
cout << m_i << endl;
}
};
Signleton Signleton::m_instance = 666;
int main(int argc, const char *argv[])
{
Signleton& s1 = Signleton::getInstance();
Signleton& s2 = Signleton::getInstance();
Signleton& s3 = Signleton::getInstance();
cout << &s1 << endl;
cout << &s2 << endl;
s1.printf();
s2.printf();
return 0;
}
3.2 懒汉式
用时再创建(懒),不用再销毁
#include <iostream>
using namespace std;
class Signleton{
private:
int m_i;
static int m_count ; //记录对象的引用次数
static Signleton *m_instance;
Signleton(int i = 0){
m_i = i;
cout << "constructor " << endl;
}
Signleton(const Signleton& that){}
public:
static Signleton& getInstance(void){
if(m_instance == NULL){
m_instance = new Signleton(123);
}
m_count++;
return *m_instance;
}
void release(){
m_count--;
if(m_count == 0){
delete m_instance;
m_instance = NULL;
}
}
~Signleton(){
cout << "destroy" << endl;
}
};
Signleton * Signleton::m_instance = NULL;
int Signleton::m_count = 0;
int main(void){
//Signleton s1; //error
Signleton& s1 = Signleton::getInstance();
Signleton& s2 = Signleton::getInstance();
Signleton& s3 = Signleton::getInstance();
cout << &s1 << " " << &s2 << " " << &s3 << endl;
s1.release();
s2.release();
s3.release();
return 0;
}