如何构造一个不能被继承的类
程序员文章站
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;
}
我们看到,这里是编不过的