[英]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.