Public new private constructor
When I try compiling the following:
#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;
}
I get :
$ 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
If the new is a member function, why can it not call the private constructor?
Edit: My idea is to create a class that can only be instantiated on the heap using totally standard syntax. I was hoping since new is a data member, it could call the pri开发者_开发百科vate constructor but since new is not used for stack objects, you would not be allowed to create the object on the stack.
I think you have a misunderstanding on what the operator new
does. It does not create objects, but rather allocates memory for the object. The compiler will call the constructor right after calling your operator 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
}
The main usage of the operator new is having a memory allocator different to the default allocator for the system (usually malloc), and it is meant to return an uninitialized region of memory on which the compiler will call the constructor. But the constructor is called after the memory is allocated in the scope where the new call was written (main in this case).
After acceptance note
The complete solution to the unformulated question: how do I force users of my class to instantiate in the heap? is to make the constructors private and offer a factory function, as shown in some other answers (as the one by villintehaspam) point out.
This is what you could do to force your object to be created on the heap:
class Foo {
public:
static Foo *Create() {
return new Foo;
}
private:
Foo() {}
};
and then when you use it:
Foo *foo = Foo::Create();
You might want to consider returning a shared_ptr instead of a raw pointer to help ensure that the object gets deleted.
This isn't technically what you asked for, but it is what you indicated that you would like to achieve...
new does not call the constructor - the compiler does, and the constructor must be accessible to it. Take this simpler code:
class A {
A() {}
public:
void * operator new( size_t x ) { return 0; }
};
int main() {
A* a = new A;
}
Obviously, new is not calling the constructor, but you will still get a "private constructor" error message if you compile it..
For the reasons badly outlined by various people what you are doing doesn't work; the way I ussually achieve your 'not on the stack' goal is like so
class HeapOnly {
public:
static HeapOnly* CreateInstance() { return new HeapOnly(); }
protected:
HeapOnly() { }
};
Now the only way to instantiate it is: HeapOnly *MyObj=HeapOnly::CreateInstance();
The problem is that if the constructor is private, you cannot instantiate an object.
Why did you make your constructor private?
精彩评论