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