Open new private constructor

When I try to compile 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 a new member function, why can't it call a private constructor?

Edit: My idea is to create a class that can only be created on the heap using completely standard syntax. I was hoping that since the new data item could call a private constructor, but since the new one is not used for stack objects, you will not be allowed to create the object on the stack.

+4
source share
6 answers

I think you have a misunderstanding about what operator new does. It does not create objects, but rather allocates memory for the object. The compiler will invoke the constructor immediately after calling your new operator.

 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 use of the new operator is the memory allocation, which is different from the default allocator for the system (usually malloc), and it is intended to return the uninitialized memory area to which the compiler will invoke the constructor. But the constructor is called after allocating memory in the area where the new call was recorded (the main one in this case).

After accepting the note

Complete solution to an unformatted question: how to get users of my class to instantiate on the heap? is to make the constructors private and suggest a factory function, as shown in some other answers (as shown by villintehaspam ).

+9
source

This is what you could do to make your object 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(); 

Perhaps you should consider returning shared_ptr instead of a raw pointer to ensure that the object is deleted.

It is not technically what you asked for, but it is what you indicated that you want to achieve ...

+10
source

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 does not call the constructor, but you still get the "private constructor" error message if you compile it.

+5
source

Constructors really do not differ from other member functions in this respect: if they are marked as private , they are not accessible outside the class (for example, in main ). And since you always need to call a constructor when creating an instance, you cannot create an instance of a class object that has only private (i.e., Inaccessible) constructors.

Now, even if you do not declare any constructor yourself, the C ++ compiler will provide certain default constructors and even the default assignment operator = :

  • default constructor (without arguments): Test::Test()
  • copy constructor (using a reference to an object of a class type): Test::Test(const Test&)
  • assignment operator = : Test& Test::operator =(const Test&)

And this is where private constructors are useful: sometimes you don’t want your class to have all of these implicit implementations, or you don’t want your class to support certain types of behavior, such as assigning a copy or building a copy. In this case, you declare those members which you do not want for your class as private , for example:

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

For reasons that are poorly characterized by different people, what you do does not work; as I usually achieve the off-stack goal, it looks like

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

Now the only way to create an instance: HeapOnly * MyObj = HeapOnly :: CreateInstance ();

+1
source

The problem is that if the constructor is private, you cannot instantiate the object.

Why did you make your constructor private?

0
source

Source: https://habr.com/ru/post/1299973/


All Articles