7

I'm using OpenSplice DDS, and there, almost all C++ classes (basic ones that I used, I can mention them if that matters) have overloaded new operators to be private (to prevent users from using them). I don't understand, why would anyone do that? Could someone provide some examples that show the necessity of this?

Why I need new: Because most of these classes don't have default constructors, and I need to initialize them later in my implementation through a unique_ptr.

Easy trick: On the other hand... I can very easily trick this! I can just wrap this class with another class, and use new all I want, right? Hence I don't understand the motivation and it feels like bad style. Could someone explain?


EDIT:

Just to clarify: Providing a good example where this can't be escaped is a good answer. It'll be helpful for all people who see new operators made private.

The Quantum Physicist
  • 24,987
  • 19
  • 103
  • 189
  • 1
    `private`, `protected`, `public` don't really do anything except for guiding developers / users of your API. If you choose to circumvent your own protection, there's almost always a way to do that in C++ – stefan Feb 02 '17 at 09:17
  • 2
    Did you see [this](http://stackoverflow.com/a/124857/1870232) ? – P0W Feb 02 '17 at 09:17
  • This question is very specific to a tool/library/SW. I wish you had a tag for it. – P0W Feb 02 '17 at 09:19
  • 1
    Maybe they don't wanna you ues new directlly? Do they provide you a builder class or factory class? something like that? – John Zeng Feb 02 '17 at 09:20
  • @P0W I saw that actually first, but it doesn't answer my question, does it? The library that does that is OpenSplice DDS. I mentioned it in the first sentence. I hope I got what you meant there. – The Quantum Physicist Feb 02 '17 at 09:20
  • @TheQuantumPhysicist IMHO, title is the first thing, people look. May be it should say _"Why would you ever make operator `new` private in -OpenSplice DDS ?"_ – P0W Feb 02 '17 at 09:23
  • @JohnZeng They provide only type generators (through IDL), which I include in my implementation, but these are not involved in the problem. The classes I'm using ( e.g.,`dds::domain::DomaintParticipant`, for example, isn't a factory AFAIK. – The Quantum Physicist Feb 02 '17 at 09:23
  • I agree, it's a really bad design choice. The DomLibrary does a similar thing by preventing overloading with private members when having a specific *type* of document is more important to most applications than how it stores the data. – Mike Feb 02 '17 at 09:23
  • 1
    Assumedly the new is private because the library wants you to use some other static method to instantiate the class? – RobPethi Feb 02 '17 at 09:23
  • @P0W Actually I would like to understand the general motivation, not only for OpenSplice DDS. OpenSplice DDS is not the only place where this occurs. – The Quantum Physicist Feb 02 '17 at 09:24
  • Is the constructor also private? – M.M Feb 02 '17 at 09:27
  • @M.M Nope. If that were the case, there would be no way for me to instantiate an object at all, right? – The Quantum Physicist Feb 02 '17 at 09:28
  • 3
    @TheQuantumPhysicist nope, not right. There can be some static function like `create` that will return for example smart pointer to object. If there will be not - then ye, you are right. – ForEveR Feb 02 '17 at 09:29
  • @ForEveR I see. That didn't occur to me. But anyway, the constructor is not private. – The Quantum Physicist Feb 02 '17 at 09:30
  • 1
    Maybe the plan is to reduce the amount of forum threads by noobs who unnecessarily use pointers and cause memory bugs as a result – M.M Feb 02 '17 at 09:31
  • Easier trick: explicitly use the global operator `new` instead of a class-specific override: `foo* p = ::new foo;` – Casey Feb 02 '17 at 09:49
  • @Casey and T.C. ... OK?!! Does that even work? I never heard of global `new`... that's something I have to read about! – The Quantum Physicist Feb 02 '17 at 09:51

3 Answers3

3

why would anyone [overload new operators to be private (to prevent users from using them)]

Presumably to prevent allocating the objects directly on heap (i.e. dynamically).

Could someone provide some examples that show the necessity of this?

I don't know anything that necessitates this. Best source to find information about decision like this is the documentation. If it isn't documented, then you can ask the developers.

I can only guess. My guess is that the designers hope to make it more difficult for their users to make mistakes, by forgetting to free dynamic objects, or by trying to destroy or use non-existing ones.


EDIT: This is not provably official, but a user tagged as employee of the company that provides the library has commented on their forum:

The ISO C++ API is designed to have all objects created on the stack rather than the heap as this allows all memory management to happen automatically based on whether objects are still referred to. Copying an ISO C++ object will not incur an overhead as this will just copy the underlying smart pointer resulting in two references to the same object.


Because most of these classes don't have default constructors, and I need to initialize them later ...

That doesn't necessarily mean that you require dynamic allocation. Even though a class might not have a default constructor, it might still have a sensible default state, that can be achieved by passing some canonical value to the constructor (say, nullptr).

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326
3

Lots of embedded C++ need to guarantee that NO dynamic allocations are done once the system is started. The aeronautics, automotive and medical device industry often have this requirement. See the following links for such coding standards and the rational behind it:

Mike P
  • 742
  • 11
  • 26
2

You do not strictly need new.

New can be forbidden to force stack allocation of objects (as opposed to heap allocation). Consider:

struct Point {
   int x, y;
};

Point * a = new Point{3, 5}; //sizeof(Point) in heap + sizeof(Point *) in stack.
Point b{3, 5}; //sizeof(Point), directly in the stack

So if you delete operator new (in C++11 it is the right way if you want to forbid) or make it private (pre-C++11) you enforce the protocol for users.

Another reason to forbid (but not delete) newing and constructors could be to return some kind of smart pointer of your object factory:

class MyClass {
private:
    MyClass();
    void * operator new(...);
public:
    static std::shared_ptr<MyClass> create() {
       //check if object in cache...
       auto c = std::make_shared<MyClass>();
       //Do more stuff maybe
       return c;
    }
};

This would enforce something in the factory constructor if needed, such as using caches or any other thing, would forbid outside users from using new also, but would still allow using new inside the class for the allocation (if you delete operator new you cannot do this anymore).

Germán Diago
  • 7,473
  • 1
  • 36
  • 59
  • Thanks for the answer, but I know this already. The question is: Why would you wana force stack allocation? What good-style programming could there be that justifies this? If the problem is `sizeof`, there's a million other ways to resolve this issue without having to set new as private. This sounds to me like killing a fly with a bazooka. – The Quantum Physicist Feb 02 '17 at 09:29
  • vector points(10000); 10000 * sizeof(Point) vs vector ptrpoints(10000); sizeof(Point) * 10000 + sizeof(Point *) * 10000. This would double the memory needed assuming an architecture where pointers are 8 bytes and int 32 bits each. I find it a good reason. But that depends on how you use the type on the client side, of course. – Germán Diago Feb 02 '17 at 09:38
  • Does my comment reply your question? If it does, let me know, I will add it to the reply directly. @TheQuantumPhysicist – Germán Diago Feb 02 '17 at 09:40
  • Not really. This is just bad style! Size of an object is not a justification to forbid `new`. Honestly, again, fly-bazooka. – The Quantum Physicist Feb 02 '17 at 09:43
  • The factory thing is probably a good justifiation, though it's not the case in the library I'm using. I'll wait and see if better answers come up. – The Quantum Physicist Feb 02 '17 at 09:44
  • @TheQuantumPhysicist Size of an object is not a justification depends on who are the users of your library, lol! It can forbid accidents. Let us say that doing so could exhaust memory and provoke some kind of bigger problem... Anyway, I think you will not find what you are looking for honestly, because I have been using C++ since 2002 and I would be surprised to find a justifcation for forbiding it beyond style or circumstances of use. I do not know of any. – Germán Diago Feb 02 '17 at 09:52
  • Well, you're probably right. But in my opinion, forbidding people from using `new` because of a problem that might happen due to lack of experience, is like forbidding people from reading a book, because it may make them change or lose their faith. This is C++, not Java. It has way more freedom that should not be taken away just for the assumption that I have unexperienced people using it. – The Quantum Physicist Feb 02 '17 at 10:00
  • @TheQuantumPhysicist this is not what they were thinking when they wrote it I may guess... at the end, it is a decision tradeoff. And a question of style. You may be right, but we humans disagree on how to treat the same problem. :) – Germán Diago Feb 02 '17 at 10:06