C++无法被继承的类实现以及单例模式的类的实现
来源:互联网 发布:手机流量开关软件 编辑:程序博客网 时间:2024/06/08 19:00
无法被继承的类的实现
思路
构造函数是类的私有成员函数,同时在共有成员函数里,声明创建该类的实例的函数。以及释放该类的析构函数。
范例
#include<iostream>using namespace std;class A{public: static A * Construct(int n) { A *pa = new A; pa->num = n; cout << "num is:" << pa->num << endl; return pa; } static void Destruct(A * pIntance) { delete pIntance; pIntance = NULL; }private: A(){} ~A(){}public: int num;};class B:public A//如果后面声明一个B的实例,则报错{};void main(){ A *f = A::Construct(9); cout << f->num << endl; A::Destruct(f); // B b;//error error: ‘A::A()’ is private}
上面这个类不可以实现在栈上创建对象。也就是说,仅仅只可以在堆上构建任何的一个对象,而在栈上就无能为力了。
私有的构造函数极大的局限性就这样一览无余了。(其实,上面类设计即是一种只可以创建堆对象,不可以创建栈对象的情况。
i
a在栈上建立一个类的对象,需要使用下面的方法:
#include<iostream>using namespace std;template <typename T>class Base{ friend T;private: Base() {} ~Base() {}};class Finalclass : virtual public Base<Finalclass>{public: Finalclass() {} ~Finalclass() {}};class TestClass : public Finalclass{};int main(){ Finalclass* p = new Finalclass; // 堆上对象 Finalclass fs; // 栈上对象 // TestClass tc; // 基类构造函数私有,不可以被继承。因此不可以创建栈上对象。return 0;}
当派生类TestClass在构造对象时,因为是虚继承,所以派生类TestClass的构造函数会直接去调用Base基类的构造函数,而Base的构造函数是私有的。编译错误!
单例模式
#include <iostream>using namespace std;class CSingleton{private: CSingleton() //构造函数是私有的 { } static CSingleton *m_pInstance;public: static CSingleton * GetInstance() { if(m_pInstance == NULL) //判断是否第一次调用 m_pInstance = new CSingleton(); return m_pInstance; }};CSingleton *CSingleton ::m_pInstance=NULL;//一定要初始化int main(){ CSingleton* p0 = CSingleton :: GetInstance(); CSingleton* p1 = CSingleton :: GetInstance(); CSingleton* p2 = p1->GetInstance(); CSingleton & ref = * CSingleton :: GetInstance(); cout<<p0<<endl;//0xfcd010 cout<<p1<<endl;//0xfcd010 cout<<p2<<endl;//0xfcd010 cout<<&ref<<endl;//0xfcd010 return 0;}
另外测试
#include<iostream>using namespace std;class CSingleton{private: CSingleton() { cout<<"调用Csingleton 的构造函数"<<endl;} static CSingleton *m_pInstance; class CGarbo { public: ~CGarbo() { cout<<"调用CGarbo的析构函数"<<endl; if(CSingleton::m_pInstance) { delete CSingleton::m_pInstance; cout<<"delete CSingleton::m_pInstance;"<<endl; } } }; static CGarbo Garbo; public: static CSingleton * GetInstance() { cout<<"调用GetInstance"<<endl; if(m_pInstance == NULL) { cout<<"m_pInstance == NULL"<<endl; m_pInstance = new CSingleton(); } return m_pInstance; }};CSingleton* CSingleton ::m_pInstance=NULL;CSingleton::CGarbo CSingleton::Garbo;class aclass{public: int c; static int a; static void fun(){cout<<a<<endl;}//静态函数只能访问静态成员 void fun2(){cout<<a<<endl;}}; int aclass::a=0; //初始化int main(){ CSingleton* p1 = CSingleton :: GetInstance(); CSingleton* p2 = p1->GetInstance();CSingleton & ref = * CSingleton :: GetInstance();aclass A;A.a++;cout<<A.a<<endl;aclass B;B.a++;cout<<B.a<<endl;cout<<aclass::a<<endl;B.fun();A.fun2();return 0;}//输出:调用GetInstancem_pInstance == NULL调用Csingleton 的构造函数调用GetInstance调用GetInstance调用CGarbo的析构函数delete CSingleton::m_pInstance;12222/对于单例函数的析构函数写法:第一种想法:怎么在程序结束的时候对其释放尼。基本的思路是定义一个内部类,然后再类内部定义一个内部类的对象,这样在程序结束的时候,在释放内部类对象的时候会调用内部类的析构函数,我们就可以将所有的释放操作放在内部类的析构函数中进行。
z注意得加上这一句,初始化Garbo。
CSingleton::CGarbo CSingleton::Garbo;
第二种想法:
单例模式另外两个写法:
http://www.2cto.com/kf/201403/283007.html
补充一点静态成员函数知识
1.静态成员函数的地址可用普通函数指针储存,而普通成员函数地址需要用 类成员函数指针来储存。举例如下:
class base{
static int func1();
int func2();
};
int (*pf1)()=&base::func1;//普通的函数指针
int (base::*pf2)()=&base::func2;//成员函数指针
2.静态成员函数不可以调用类的非静态成员。因为静态成员函数不含this指针。
3.静态成员函数不可以同时声明为 virtual、const、volatile函数。举例如下:
class base{
virtual static void func1();//错误
static void func2() const;//错误
static void func3() volatile;//错误
};
最后要说的一点是,静态成员是可以独立访问的,也就是说,无须创建任何对象实例就可以访问。
e为什么静态成员函数只能只能访问静态成员?
和静态数据成员一样,静态成员函数是类的一部分,而不是对象的一部分。如果要在类外调用公用的静态成员函数,要用类名和域运算符“∷”。如 Box∷volume( ); 实际上也允许通过对象名调用静态成员函数,如 a.volume( ); 但这并不意味着此函数是属于对象a的,而只是用a的类型而已。 静态成员函数的作用是为了能处理静态数据成员。 可以说,静态成员函数与非静态成员函数的根本区别是:非静态成员函数有this指针,静态成员函数并不属于某一对象,它与任何对象都无关,静态成员函数没有this指针。由此决定了静态成员函数不能访问本类中的非静态成员。 在C++程序中,静态成员函数主要用来访问静态数据成员,而不访问非静态成员。假如在一个静态成员函数中有以下语句: cout << height<< endl; //若height已声明为static,则引用本类中的静态成员,合法 cout << width<< endl; //若width是非静态数据成员,不合法 但是,并不是绝对不能引用本类中的非静态成员,只是不能进行默认访问,因为无法知道应该去找哪个对象。如果一定要引用本类的非静态成员,应该加对象名和成员运算符“.”。如 cout<< a.width << endl; //引用本类对象a中的非静态成员。
类的静态成员(变量和方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问;非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问。
在一个类的静态成员中去访问其非静态成员之所以会出错是因为在类的非静态成员不存在的时候类的静态成员就已经存在了,访问一个内存中不存在的东西当然会出错:class CA{private:int a; //非静态成员,创建类的实例时分配内存,类的不同实例对应不同的内存区域
- C++无法被继承的类实现以及单例模式的类的实现
- 实现一个无法被继承的类
- 【C/C++学院】0822-类型转换函数与构造转换函数/类的继承/类的继承以及区别/继承静态成员与静态函数//继承实现代码重用/单继承QT案例/多继承简介以及实战/Gpu编程
- 【Objective-C】单例模式的实现
- Objective-C 单例模式的实现
- c++--Singleton单例模式的实现
- <剑指offer>深度探索(一)实现string 类以及单例模式的具体实现
- 类、接口继承以及接口的实现
- [C++] 单件模式的一般实现
- 实现一个无法被继承的C++类
- 实现一个无法被继承的C++类
- 实现一个无法被继承的C++类
- 实现一个无法被继承的C++类
- 实现一个无法被继承的C++类(转)
- 实现一个无法被继承的C++类
- 实现一个无法被继承的C++类
- 实现一个无法被继承的C++类
- 单例模式的实现
- 【问题解决】MYSQL 服务无法启动,错误日志:InnoDB: .\ibdata1 must be writable
- 169. Majority Element
- Mac OS X 安装 Nginx
- jsp连接mysql数据库,实现含验证码的用户登录
- Laravel中用Redis来做任务队列---出现重载问题
- C++无法被继承的类实现以及单例模式的类的实现
- Python练习1-文档格式化成html
- yii1.1model属性动态添加
- 归并排序(Merge sort)
- Java 重载、重写、构造函数详解
- windows下用 caffe 训练MNIST数据
- mysql二进制日志
- jQuery
- 17.5.4 学习总结 段落方面