欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

如何构造一个不能被继承的类

程序员文章站 2022-06-01 13:42:22
...


一.实现一个不能被继承的类

      拿到这个题,思考这个类不能被继承说明这个类的派生类是不能被构造出来的,我们就可以从构造函数下手。
    子类对象要是想被创建出来,那么就一定会调用自己的构造函数,而且自己的构造函数是由父类的构造函数合成的,如果把父类的构造函数限定为私有的,无论是哪种继承方式,对子类都是不可见,那么子类对象就不能被构造出来了。这样就达到了不能被继承。
   但是如果父类的构造函数限定为私有的话,类外面不能直接访问,自己也就不能构造出来了,所以要类里面这里要实现有一个静态成员函数来构造处对象。而且一定是静态的,如果是普通成员函数,是只能通过对象来调用,但是正是要用这个函数来构造我们的对象 。但是如果声明为静态的,这个函数就属于整个类域,就可以不通过对象来调用而构造出对象。
具体实现方法看下面代码:

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;
}


如何构造一个不能被继承的类

我们看到,这里是编不过的