C++:内嵌类、静态成员变量和函数、单例模式、友元函数和友元类
来源:互联网 发布:163邮箱大师 mac 编辑:程序博客网 时间:2024/04/29 18:27
一、内嵌类
1. 什么是内嵌类:
内嵌类是指,一个类定义在另一个类的内部。
2. 类内声明,类外实现的方法:
返回类型 外部类::内嵌类::函数名(形参表) {...}
二、静态成员变量与函数 static //全局的,作用域在类内
1. 静态成员变量/对象
1)静态成员变量的声明
class A {
static 对象类型 对象名(变量名);
};
2)静态成员变量的定义
对象类型 类名(A)::对象名 = 初值;
或
对象类型 类名(A)::对象名;
3)访问权限:公有,保护,私有
4)使用方法:
<1>在类内:直接用变量名访问
<2>在类外:
类名::静态成员变量名
或
对象名.静态成员变量名
补充:
//C语言的静态全局变量可见范围为当前.c文件内
static int s_money = 0;
//C语言的静态函数的可见范围为当前.c文件内有效,C++也一样
static int * get_money_ptr() {
return &s_money;
}
2. 静态成员函数
1)静态成员函数的声明:
class 类名 {
static 返回类型 函数名(形参表); //类内声明
static 返回类型 函数名(形参表) {...} //类内声明,类内实现
};
返回类型 类名::函数名(形参表) {...} //类外实现
2)说明
<1>静态成员函数/对象不属于某个对象,它属于某个类公有;
<2>静态成员函数内部没有 this 指针,它不能访问对象的成员变量;
<3>静态成员函数不能为常成员函数,即不能用 const 修饰;
三、单例模式 (静态成员函数的应用 - 23 中模式之一)
1)说明:
在整个应用程序内部,"在同一时刻,只允许有一个对象存在"的模式。
单例模式包含:
1. 禁止在类外部创建对象实例(私有构造函数 private)
2. 类自己维护其唯一实例(静态成员变量 static instance)
3. 提供访问该实例的方法(静态成员函数 static getInstance)
2)单例模式的实现方法:
<1>【饿汉式】:
将唯一的对象实现为静态成员对象,无论用与不用,程序启动就创建。
"优点":加载进程时创建单例对象,线程安全。
"缺点":无论是否使用,此对象一直存在,成员较大时占内存资源。
<2>【懒汉式】:
在需要的时候才动态创建这个对象,否则先不创建这个对象。
"优点":需要使用时,才创建单例对象,使用时才占内存资源。
"缺点":首次访问单例对象时,需要考虑线程安全("线程锁解决")。
四、成员指针 (仅作了解,可以不用)
1. 成员变量指针
1)语法定义:
类型 类名::*成员指针名;
或
类型 类名::*成员指针名 = &类名::成员对象名;
2)用法:(解引用)
对象.*成员指针
对象指针->*成员指针
int i = 10;
int *pi = &i;
*pi = 10; //*号也叫解引用运算符
2. 成员函数指针
1)定义语法:
返回类型 (类名::*成员函数指针)(形参表); //定义
或 //定义并初始化
返回类型 (类名::*成员函数指针)(形参表) = &类名::非静态成员函数名;
2)用法:
(对象.*成员函数指针名)(实参);
(对象指针->*成员函数指针名)(实参);
五、友元函数
关键字 friend 全局函数返回值类型声明;
1. 友元函数的声明方法:
类内:friend 全局函数声明;
2. 说明
1)友元函数非成员函数,并且不受访问权限限定符限制;
2)友元函数只能是全局函数(不能是类内成员函数);
六、友元类
关键字 friend class 类名;
class A { };
class B {
friend class A;
};
1. 友元类A可以访问B类内所有类型的成员,不受访问限定符限制;
2. 说明:
1)友元类不能反向递推,A类为B类的友元,但B类不是A类的友元。
【总的说明】 友元实际破坏了类的封装性,最好少用或不用友元。
1. 什么是内嵌类:
内嵌类是指,一个类定义在另一个类的内部。
2. 类内声明,类外实现的方法:
返回类型 外部类::内嵌类::函数名(形参表) {...}
/** 代码演示 **/#include <iostream>using namespace std;class List { //双向链表public: List(): m_head(NULL), m_tail(NULL) { } private: class Node { //双向链表节点 (内嵌类) public: Node(int d); //类内声明,类外实现 //类内声明,类内实现 Node(int d): m_data(d), m_next(NULL), m_prev(NULL) { } int m_data; Node *m_next; Node *m_prev; }; public: void push_back(int v) { if(NULL == m_tail) { m_head = m_tail = new Node(v);//连续赋值 } else { //其他实现代码 } } private: Node *m_head; Node *m_tail;};List::Node::Node(int d): m_data(d), m_next(NULL), m_prev(NULL) { } int main() { List l1; //l1 链表封装 l1.push_back(100);// List::Node n1(200); //私有的就不合法// List::Node *node = new List::Node(300); return 0;}
二、静态成员变量与函数 static //全局的,作用域在类内
1. 静态成员变量/对象
1)静态成员变量的声明
class A {
static 对象类型 对象名(变量名);
};
2)静态成员变量的定义
对象类型 类名(A)::对象名 = 初值;
或
对象类型 类名(A)::对象名;
3)访问权限:公有,保护,私有
4)使用方法:
<1>在类内:直接用变量名访问
<2>在类外:
类名::静态成员变量名
或
对象名.静态成员变量名
/** 代码演示 **/#include <iostream>using namespace std;class BOC { //Bank of chinapublic: BOC(): m_money(0) {} void saveMoney(int m) { //存入非静态成员变量 m_money += m; } int getMnoey() { return m_money; } void save(int m) { s_money += m; } void showMoney() { cout << "总钱数:" << s_money << endl; } int m_money; static int s_money; //静态成员变量的声明};int BOC::s_money = 0; //定义+初始化int main(void) { cout << BOC::s_money << endl; //1. 用类来访问 BOC t1; t1.save(1000); //存入静态成员变量中 cout << t1.s_money << endl; //2. 用对象来访问 t1.showMoney(); //3. 用成员函数来访问 return 0;}
补充:
//C语言的静态全局变量可见范围为当前.c文件内
static int s_money = 0;
//C语言的静态函数的可见范围为当前.c文件内有效,C++也一样
static int * get_money_ptr() {
return &s_money;
}
2. 静态成员函数
1)静态成员函数的声明:
class 类名 {
static 返回类型 函数名(形参表); //类内声明
static 返回类型 函数名(形参表) {...} //类内声明,类内实现
};
返回类型 类名::函数名(形参表) {...} //类外实现
2)说明
<1>静态成员函数/对象不属于某个对象,它属于某个类公有;
<2>静态成员函数内部没有 this 指针,它不能访问对象的成员变量;
<3>静态成员函数不能为常成员函数,即不能用 const 修饰;
/** 代码演示 **/#include <iostream>using namespace std;class A { public: A() { s_global++; } //构造函数,根据静态变量的值知道对象个数 ~A() { s_global--; } static int getCount() { //【静态成员函数】类内声明+实现 return s_global; } static void reset(); // 【静态成员函数】类内声明+类外实现 int m_a1; //4个字节private: static int s_global; //静态成员变量不占对象的空间};void A::reset() { s_global = 0 }; //类外实现int A::s_global = 0; //全局void test() { cout << A::getCount() << endl;}int main(void) { cout << A::getCount() << endl;//0 test();//0 A a; cout << sizeof(a) << endl; //4 cout << a.getCount() << endl;//1 A *p = new A; cout << a.getCount() << endl;//2 test();//2 delete p; p = NULL; test();//1 A::reset(); cout << a.getCount() << endl;//0// cout << a.s_global << endl; //0 (公有权限)// cout << A::s_global << endl; //0 (公有权限) return 0;}
三、单例模式 (静态成员函数的应用 - 23 中模式之一)
1)说明:
在整个应用程序内部,"在同一时刻,只允许有一个对象存在"的模式。
单例模式包含:
1. 禁止在类外部创建对象实例(私有构造函数 private)
2. 类自己维护其唯一实例(静态成员变量 static instance)
3. 提供访问该实例的方法(静态成员函数 static getInstance)
2)单例模式的实现方法:
<1>【饿汉式】:
将唯一的对象实现为静态成员对象,无论用与不用,程序启动就创建。
"优点":加载进程时创建单例对象,线程安全。
"缺点":无论是否使用,此对象一直存在,成员较大时占内存资源。
/** 代码演示 **/#include <iostream>using namespace std;class Singleton {public: static Singleton & getInstance() { return s_instance; } void doSomething() { cout << "单例对象正在做事...\n"; } private: Singleton() {} //私有的构造函数// Singleton *a; //这样定义在成员的上面合法,如链表:Node *next; int bmp[1920*1080]; //很大 int s_member; //单例里的随意成员 static Singleton s_instance; //实例(先有占内存的成员变量)};Singleton Singleton::s_instance; //静态成员变量需要在类的外部实例化int main() { //getInstance()为单例模式的接口,使用接口需要用引用接收 Singleton & a1 = Singleton::getInstance(); a1.doSomething(); Singleton & a2 = Singleton::getInstance(); a2.doSomething(); //类的对象始终只有一个 return 0;}
<2>【懒汉式】:
在需要的时候才动态创建这个对象,否则先不创建这个对象。
"优点":需要使用时,才创建单例对象,使用时才占内存资源。
"缺点":首次访问单例对象时,需要考虑线程安全("线程锁解决")。
/** 代码演示 - 考虑线程安全的【懒汉式】单例模式 **/#include <iostream>#include <pthread.h>using namespace std;class Singleton {public: static Singleton * getInstance() { pthread_mutex_lock(&s_lock); //线程上锁 if(NULL == s_pInstance) { s_pInstance = new Singleton; } //指针指向内容不为空才返回 pthread_mutex_unlock(&s_lock); //线程解锁 return s_pInstance; } void doSomething() { cout << "单例对象正在做事...\n"; } private: Singleton() {} //私有的构造函数 int s_member; //单例里的随意成员 static Singleton *s_pInstance; //实例(先有占内存的成员变量) static pthread_mutex_t s_lock; //声明线程锁};Singleton *Singleton::s_pInstance = NULL; //指针必须初始化//初始化线程锁pthread_mutex_t Singleton::s_lock = PTHREAD_MUTEX_INITIALIZER;void *thread_func(void *data) { Singleton *p3 = Singleton::getInstance(); p3->doSomething(); return NULL;}int main() { //getInstance()为单例模式接口,同时也是只有1个单例对象 Singleton *p1 = Singleton::getInstance(); p1->doSomething(); cout << "p1 address: " << p1 << endl; //0x9131008 Singleton *p2 = Singleton::getInstance(); p2->doSomething(); cout << "p2 address: " << p2 << endl; //0x9131008 return 0;}
四、成员指针 (仅作了解,可以不用)
1. 成员变量指针
1)语法定义:
类型 类名::*成员指针名;
或
类型 类名::*成员指针名 = &类名::成员对象名;
2)用法:(解引用)
对象.*成员指针
对象指针->*成员指针
int i = 10;
int *pi = &i;
*pi = 10; //*号也叫解引用运算符
/** 代码演示 **/#include <iostream>using namespace std;class A { public: A(): a1(1), a2(2) { } int a1; int a2; };int main() { int A::*pa = &A::a1; //成员指针 pa; 必须借助于某个对象 cout << "pa = " << pa << endl; A a; //创建a对象 cout << "a.a1 = " << a.a1 << endl; cout << "a.*pa = " << a.*pa << endl; A *p = &a; cout << "p->a1 = " << p->a1 << endl; cout << "p->*pa = " << p->*pa << endl; pa = &A::a2; cout << "p->*pa = " << p->*pa << endl; cout << "pa = " << pa << endl; return 0;}
2. 成员函数指针
1)定义语法:
返回类型 (类名::*成员函数指针)(形参表); //定义
或 //定义并初始化
返回类型 (类名::*成员函数指针)(形参表) = &类名::非静态成员函数名;
2)用法:
(对象.*成员函数指针名)(实参);
(对象指针->*成员函数指针名)(实参);
/** 代码演示 **/#include <iostream>using namespace std;class A { public: A(): a1(1), a2(2) { } void setA1A2(int i1, int i2) { cout << "setA1A2\n"; } void setA2A1(int i2, int i1) { cout << "setA1A2\n"; } int a1; int a2; };int main() { int A::*pa = &A::a1; //成员指针 pa; 必须借助于某个对象 cout << "pa = " << pa << endl; A a; //创建a对象 cout << "a.a1 = " << a.a1 << endl; cout << "a.*pa = " << a.*pa << endl; A *p = &a; cout << "p->a1 = " << p->a1 << endl; cout << "p->*pa = " << p->*pa << endl; pa = &A::a2; cout << "p->*pa = " << p->*pa << endl; cout << "pa = " << pa << endl; //以下示意成员函数指针// void (A::*pf)(int, int); void (A::*pf)(int, int) = &A::setA1A2; (a.*pf)(100, 200); //==> a.setA1A2(100, 200); pf = &A::setA2A1; (p->*pf)(1000, 2000); //==> p->setA2A1(1000, 2000); return 0;}
五、友元函数
关键字 friend 全局函数返回值类型声明;
1. 友元函数的声明方法:
类内:friend 全局函数声明;
2. 说明
1)友元函数非成员函数,并且不受访问权限限定符限制;
2)友元函数只能是全局函数(不能是类内成员函数);
六、友元类
关键字 friend class 类名;
class A { };
class B {
friend class A;
};
1. 友元类A可以访问B类内所有类型的成员,不受访问限定符限制;
2. 说明:
1)友元类不能反向递推,A类为B类的友元,但B类不是A类的友元。
【总的说明】 友元实际破坏了类的封装性,最好少用或不用友元。
/** 友元函数、友元类的代码演示 **/#include <iostream>using namespace std;class Son { //compareMoney是Son的朋友friend bool compareMoney(Son &, Son &); //友元函数,公私都可访问friend class Father; //友元类,不受访问权限限定public: Son(): m_money(0) {} void getMoney(int m) { m_money += m; } void showMoney() { cout << "我的压岁钱是" << m_money << endl; } private: int m_money; //儿子的钱包};bool compareMoney(Son & s1, Son & s2) { return s1.m_money > s2.m_money;}class Father {public: Father(): m_money(0) {} void makeMoney(int m) { m_money += m; } void makeMoney(Son & s) { //友元类让类实现单向访问 Father->Son m_money += s.m_money; s.m_money = 0; } void showMoney() { cout << "父亲的钱是" << m_money << endl; } private: int m_money;//父亲的钱包};int main(void) { Son xiaowei; Son xiaoyang; xiaowei.getMoney(100); xiaoyang.getMoney(200); if(compareMoney(xiaoyang, xiaowei)) { cout << "小杨钱多\n"; } else { cout << "小魏钱多\n"; } Father laowei; laowei.makeMoney(800); laowei.makeMoney(xiaowei); laowei.showMoney(); return 0;}
0 0
- C++:内嵌类、静态成员变量和函数、单例模式、友元函数和友元类
- Day41、静态成员变量、静态成员函数、单例模式、成员/成员函数指针、操作符重载、友元函数
- 第2.5节:静态成员和友元函数(C++)
- 静态成员函数和友元
- C/C++静态成员变量和静态成员函数
- c++:静态成员变量和静态成员函数使用问题
- 静态成员变量和静态成员函数
- 静态成员函数和静态成员变量
- 静态成员变量 和 静态成员函数
- 静态成员变量和静态成员函数
- 静态成员变量和静态成员函数
- 静态成员变量和静态成员函数
- 静态成员变量和静态成员函数
- 静态成员变量和静态成员函数
- 静态成员变量和静态成员函数
- 静态成员变量和静态成员函数
- 静态成员函数和静态成员变量
- 静态成员变量和静态成员函数
- 计算机教务系统审批流程开发详细
- Android Studio不安装opencv manager配置
- springMVC注解
- 剖析同步器(转载)
- Java-JDK各个版本的新特性
- C++:内嵌类、静态成员变量和函数、单例模式、友元函数和友元类
- Android学习十二---在android上实现图像匹配
- C++笔记之类外定义
- H264分析源码学习之结构体篇——nal_t结构体
- Linux网卡数据流路径
- 小练习 - 排序:冒泡、选择、快排
- mysql 协议的ColumnDefinition包及解析
- 对象移动
- |BZOJ 1477|扩展欧几里得算法|青蛙的约会