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


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

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

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



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


猜你喜欢

转载自blog.csdn.net/misszhoudandan/article/details/80067963