一.实现一个不能被继承的类
拿到这个题,思考这个类不能被继承说明这个类的派生类是不能被构造出来的,我们就可以从构造函数下手。
子类对象要是想被创建出来,那么就一定会调用自己的构造函数,而且自己的构造函数是由父类的构造函数合成的,如果把父类的构造函数限定为私有的,无论是哪种继承方式,对子类都是不可见,那么子类对象就不能被构造出来了。这样就达到了不能被继承。
但是如果父类的构造函数限定为私有的话,类外面不能直接访问,自己也就不能构造出来了,所以要类里面这里要实现有一个静态成员函数来构造处对象。而且一定是静态的,如果是普通成员函数,是只能通过对象来调用,但是正是要用这个函数来构造我们的对象 。但是如果声明为静态的,这个函数就属于整个类域,就可以不通过对象来调用而构造出对象。
具体实现方法看下面代码:
class AA { public : static AA * GetAAObject(int a,int x)//这里多传了一个x,是想和下面的方法进行区分 { cout << "static AA * GetAAObject(int a,int x)" << endl; return new AA(a); } static AA GetAAObject(int a) { cout << "static AA GetAAObject(int a)" << endl; return AA(a);//传值是用拷贝构造 } void show() { cout << "a:"<<_a << endl; } private: AA(const int a = 0) :_a(a) { } int _a; }; class BB :public AA { public : BB(const int a = 0, const int b = 0) :AA(a), _b(b) { cout << "BB(const int a = 0, const int b = 0)" << endl; } private: int _b; }; int main() { BB b(1, 2); /*AA a = AA::GetAAObject(1); AA *p = AA::GetAAObject(2,-1); a.show(); (*p).show(); AA b(a); b.show();*/ system("pause"); return 0; }
可以试着编译一下上面的代码,会发现上面的AA类就是一个不能被继承的类,当我们想继承AA类构造BB类时,程序编不过
我们的AA类是可以正常使用的,运行下面的代码:
class AA { public : static AA * GetAAObject(int a,int x) { cout << "static AA * GetAAObject(int a,int x)" << endl; return new AA(a); } static AA GetAAObject(int a) { cout << "static AA GetAAObject(int a)" << endl; return AA(a);//传值是用拷贝构造 } void show() { cout << "a:"<<_a << endl; } private: AA(const int a = 0) :_a(a) { } int _a; }; //class BB :public AA //{ //public : // BB(const int a = 0, const int b = 0) :AA(a), _b(b) // { // cout << "BB(const int a = 0, const int b = 0)" << endl; // } //private: // int _b; //}; int main() { //BB b(1, 2); AA a = AA::GetAAObject(1); AA *p = AA::GetAAObject(2,-1); a.show(); (*p).show(); AA b(a); b.show(); system("pause"); return 0; }
执行结果:
二.实现一个只能在栈上生成对象的类
根据上面一个题的启发,我们想到可以从构造函数上入手,将构造函数声明为私有的,再自己写一个接口实现
方法一:
class AA { public : static AA GetAAObject(int a) { cout << "static AA GetAAObject(int a)" << endl; return AA(a);//传值是用拷贝构造 } void show() { cout << "a:"<<_a << endl; } private: AA(const int a = 0) :_a(a) { } int _a; }; int main() { /*AA a = AA::GetAAObject(1); a.show();*/ AA * p = new AA; system("pause"); return 0; }
上面代码我们想new一个对象时,程序编不过,就解决了只在栈上创建对象。
可能有人想到,也可以将new这条路封死,因为new对象时是这样的,new 会调用operator new()这个函数,我们就将operator new();声明为私有的,并且不进行定义,让其在类外不可用,就不会在堆上创建对象了。
方法二:
class AA { public : AA(const int a = 0) :_a(a) { } void show() { cout << "a:"<<_a << endl; } private: void * operator new(size_t size); void operator delete(void *p); //注意这里的函数重载的operator new(size_t); //用new 构造对象时,就会调用类里面的operator new(),就不会去调用全局的operator int _a; }; int main() { /*AA a = AA::GetAAObject(1); a.show();*/ AA * p = new AA(1); system("pause"); return 0; }
这样发现就不会在堆上开辟空间了
但是这样虽然封死了堆上创建对象,但是我们可以在全局区创建对象
class AA { public : AA(const int a = 0) :_a(a) { } void show() { cout << "a:"<<_a << endl; } private: void * operator new(size_t size); void operator delete(void *p); //注意这里的函数重载的operator new(size_t); //用new 构造对象时,就会调用类里面的operator new(),就不会去调用全局的operator int _a; }; AA a(2);//这样的会就可以在全局区构造出这个对象 int main() { a.show(); system("pause"); return 0; }
这样的话我们就可以在全局 区创建一个对象,也并没有达到我们的要求
但是第一种方法就不会存在这样的问题,因为只要将构造函数封死了,即使是在全局区,也是要调用构造函数的,这样的话也就不能实现对象的创建。
所以我们不推荐第二种方法。
三.实现一个只能在堆上生成对象的类
同样只能在堆上创建对象,也从构造函数入口,再实现一个接口来实现在堆上创建对象class AA { public: static AA *GetAAObject(int a,int b)//注意,这里是为了区分两种实现方法,多加了一个参数b { cout << "static AA GetAAObject(int a)" << endl; return new AA(a);//在栈上创建的对象 } static AA& GetAAObject(int a) { AA *p=new AA(a); cout << "static AA& GetAAObject(int a)" << endl; return (*p); } void show() { cout << "a:" << _a << endl; } private: AA(const int a = 0) { _a = a; } int _a; }; int main() { /*AA a = AA::GetAAObject(1); a.show(); AA *p = AA::GetAAObject(2,2); (*p).show();*/ AA b(1); system("pause"); return 0; }
我们看到,这里是编不过的