簡體   English   中英

公共新的私有構造函數

[英]Public new private constructor

當我嘗試編譯以下內容時:

#include <iostream>

class Test
{
public:
    void* operator new (size_t num);
    void operator delete (void* test);
    ~Test();
private:
    Test();
};

Test::Test()
{
    std::cout << "Constructing Test" << std::endl;
}

Test::~Test()
{
    std::cout << "Destroying Test" << std::endl;
}

void* Test::operator new (size_t num)
{
    ::new Test;
}

void Test::operator delete(void* test)
{
    ::delete(static_cast<Test*>(test));
}

int main()
{
    Test* test = new Test;
    delete test;
}

我明白了:

$ g++ -o test test.cpp
test.cpp: In function ‘int main()’:
test.cpp:14: error: ‘Test::Test()’ is private
test.cpp:36: error: within this context

如果new是一個成員函數,為什么它不能調用私有構造函數?

編輯:我的想法是創建一個只能使用完全標准語法在堆上實例化的類。 我希望因為new是一個數據成員,它可以調用私有構造函數,但由於new不用於堆棧對象,所以不允許在堆棧上創建對象。

這是您可以執行的操作,以強制在堆上創建對象:

class Foo {
public:
    static Foo *Create() {
         return new Foo;
    }
private:
    Foo() {}
};

然后當你使用它時:

Foo *foo = Foo::Create();

您可能需要考慮返回shared_ptr而不是原始指針,以幫助確保刪除對象。

這在技術上並不是你所要求的,但它是你表示你希望實現的......

我認為你對operator new功能有誤解。 它不會創建對象,而是為對象分配內存。 編譯器將在調用new new后立即調用構造函數。

struct test {
   void * operator new( std::size_t size );
};
int main()
{
   test *p = new test;
   // compiler will translate this into:
   //
   // test *p = test::operator new( sizeof(test) );
   // new (static_cast<void*>(p)) test() !!! the constructor is private in this scope
}

operator new的主要用途是使內存分配器與系統的默認分配器(通常是malloc)不同,它意味着返回一個未初始化的內存區域,編譯器將在該區域內調用構造函數。 但是,在寫入新調用的作用域中分配內存調用構造函數(在本例中為main)。

驗收完畢后

未規范問題的完整解決方案: 如何強制我的類用戶在堆中實例化? 是將構造函數設為私有並提供工廠函數,如其他一些答案所示(如villintehaspam所述 )。

new不會調用構造函數 - 編譯器會這樣做,並且構造函數必須是可訪問的。 拿這個更簡單的代碼:

class A {
    A() {}
public:
    void * operator new( size_t x ) { return 0; }
};

int main() {
    A* a = new A;
}

顯然,new不會調用構造函數,但是如果編譯它仍然會得到“私有構造函數”錯誤消息。

在這方面,構造函數與其他成員函數沒有什么不同:如果它們被標記為private ,則它們在類外是不可訪問的(例如在main )。 而且,因為在實例化期間, 總是需要調用構造函數,所以不能實例化只具有private (即不可訪問)構造函數的類的對象。

現在,即使您沒有自己聲明任何構造函數,C ++編譯器也會提供某些默認構造函數,甚至是默認賦值運算符=

  • 默認構造函數(沒有參數): Test::Test()
  • 復制構造函數(獲取類的類型的對象引用): Test::Test(const Test&)
  • 賦值運算符=Test& Test::operator =(const Test&)

這正是private構造函數有用的地方:有時,您不希望您的類具有所有這些隱式實現,或者您不希望您的類支持某些行為,例如復制賦值或復制構造。 在這種情況下,您將那些您不希望您的類成員聲明為private ,例如:

class Test
{
private:
    Test(Test& init) { }  // <-- effectively "disables" the copy constructor
}

由於各種人員嚴重概述的原因,你所做的事情是行不通的; 我實際上實現你的“不在堆疊”目標的方式是這樣的

class HeapOnly {
  public:
    static HeapOnly* CreateInstance() { return new HeapOnly(); }
  protected:
    HeapOnly() { }
};

現在實例化它的唯一方法是:HeapOnly * MyObj = HeapOnly :: CreateInstance();

問題是如果構造函數是私有的,則無法實例化對象。

為什么你的構造函數是私有的?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM