面试常问----------如何实现一个只能在栈/堆上生成对象的类

1、只能在栈上生成对象的类

只能在栈上生成对象就有两点要求:1、不能在堆上生成对象(不能借助new),2、生命周期要随栈的释放
方案1:
不借助new,我们可以在类内部借助函数构造一个对象返回,我们知道在类外调用成员函数,必须借助对象才能调用,那么使用static来修饰这个函数,这个成员函数就属于所有对象就可以直接调用。

class AA{
public:
   static AA GetObj(int a){
   return AA(a);
   }
private:
   AA(int a=0)
    :_(a)
   {}
   int _a;
};
int main(){
AA q;//站上创建
AA* p=new AA;//堆上创建
return 0;
}

方案2:
截断用new的方式来创建对象,new底层又是operator new();所以直接将operator new定义成私有,而且只声明不定义,保证在类外无法定义也无法使用。

class AA{
private:
    void* operator new(size_t size);
    void  operator delete(void * p);
public:
     AA(){
     cout<<"AA()"<<endl;
     }
     ~AA(){
     cout<<"~AA()"<<endl;
     }
     int _a;
};

此时构造函数和析构函数根本就不会被调用。

只能在堆上生成对象的类

方案1:
讲生成一个不能被继承的类的时候,我们重新定义接口返回对象,用static来修饰此函数,内部返回对象用new的方式,那就只能在堆上创建对象。

class AA{
publicstatic getobj(){
   return new AA;
   }  
private: 
  int _a;
  AA(const AA& a);
  AA& operator=(const AA& a);
};
int main(){
  AA* p=AA::getobj();//堆上
 // AA* q(p);//栈上
 return 0;
  }

产生上述问题是因为创建对象在堆上了,但是通过拷贝和赋值又会将对象创建在栈上,所以我们可以将这两条封死,把拷贝函数和赋值运算符重载只声明不定义(仿拷贝),并且定义成私有
方案2:
将类的析构函数定义成私有,编译器无法调用析构函数来释放内存,所以编译器就会在为类的对象分配空间的时候分配栈空间时,先检查函数的访问性,如果发现析构函数是私有的那么就不会将对象创建在栈上,就能实现只在堆上生成对象。

猜你喜欢

转载自blog.csdn.net/cx2479750196/article/details/80781873
今日推荐