当我尝试编译以下内容时:
#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不用于堆栈对象,所以不允许在堆栈上创建对象。
答案 0 :(得分:10)
这是强制在堆上创建对象的方法:
class Foo {
public:
static Foo *Create() {
return new Foo;
}
private:
Foo() {}
};
然后当你使用它时:
Foo *foo = Foo::Create();
您可能需要考虑返回shared_ptr而不是原始指针,以帮助确保删除对象。
这在技术上并不是你所要求的,但这是你表示你希望实现的......
答案 1 :(得分:9)
我认为你对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所指出的那个)指出。
答案 2 :(得分:5)
new不会调用构造函数 - 编译器会这样做,构造函数必须可以访问它。拿这个更简单的代码:
class A {
A() {}
public:
void * operator new( size_t x ) { return 0; }
};
int main() {
A* a = new A;
}
显然,new不会调用构造函数,但如果编译它仍然会出现“私有构造函数”错误消息..
答案 3 :(得分:1)
在这方面,构造函数与其他成员函数没有什么不同:如果它们被标记为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
}
答案 4 :(得分:1)
由于各种人员严重勾勒的原因,你所做的事情是行不通的;我实际上实现你的“不在堆叠”目标的方式是这样的
class HeapOnly {
public:
static HeapOnly* CreateInstance() { return new HeapOnly(); }
protected:
HeapOnly() { }
};
现在实例化它的唯一方法是: HeapOnly * MyObj = HeapOnly :: CreateInstance();
答案 5 :(得分:0)
问题是如果构造函数是私有的,则无法实例化对象。
为什么要将构造函数设为私有?