面試常問----------如何實現一個只能在棧/堆上生成對象的類

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:
將類的析構函數定義成私有,編譯器無法調用析構函數來釋放內存,所以編譯器就會在爲類的對象分配空間的時候分配棧空間時,先檢查函數的訪問性,如果發現析構函數是私有的那麼就不會將對象創建在棧上,就能實現只在堆上生成對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章