6

I've seen a constructor = delete explanation here but I'm wondering if I should forbid destructor calls as well. I'm trying to use a class like this:

class A
{
public:
    static bool foo(const char* filePath);
    static void foo(const int something);
private:
    A() = delete;
    ~A();
};

Should I also write like ~A() = delete; as well? Does it even matter?

Community
  • 1
  • 1
JohnJohn
  • 325
  • 1
  • 6
  • 17

3 Answers3

9

~A() = delete; is redundant, because since you cannot create an object, there is no point of worrying about destructor.

In fact with your code even there is no need of A() = delete;, because all the class members are static.
As Luchian rightly mentioned in the comment, such class are better be declared as a namespace. Underlying data can be made extern / static depending on the requirement.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 4
    Must be a Java-coder in remission. Those are forced to use classes however inappropriate that is. – Deduplicator Jan 29 '15 at 09:04
  • 1
    @Deduplicator, actually the OP is referring to LuchianGrigore's question only, and he is not a Java coder. He himself has commented to the question. :-) I know he is good in C++. – iammilind Jan 29 '15 at 09:05
  • 1
    Just looked at it. You must have meant answer, and he's not advocating doing so, just commenting on the difference to declaring it private... I concede he looks well-versed in C++. – Deduplicator Jan 29 '15 at 09:16
  • Delete destructor can warn about implement other constructors. – Isaac Pascual Feb 14 '18 at 14:31
  • 1
    Bullshit. Deleting default constructor does not forbid creating instance of an object. Same with `static` on object's members. And finally: no, it's not _better_ to change object to a `namespace`. You can't, for example, _initialize a `namespace`_. Can't `decltype` of a `namespace`. Can't make pointer to a `namespace`, etc. Not even mentioning how'd you ever define _better_? –  Jul 10 '19 at 15:51
8

(Note: In C++20, deleting the constructor of an aggregate now makes the type impossible to construct, so no more unexpected behavior)

To add to the other answers here, you might want to declare the destructor as deleted instead of as private and not implemented. This is because, even with a private deleted constructor, you can still use aggregate initialization to create an instance:

Demo

class A
{
public:
    static bool foo(const char* filePath);
    static void foo(const int something);
private:
    A() = delete;
};

int main(){
   A a{}; // whoops I just created an instance
}

However, if you declare the destructor as deleted, neither default construction or aggregate initialization will work -- it fails to compile because the compiler cannot invoke the destructor for A

Demo

class A
{
public:
    static bool foo(const char* filePath);
    static void foo(const int something);
    ~A() = delete;
};

int main(){
   A a{}; // fails
   A b; // fails
}

Since you've already declared your destructor as private and not implemented, all the other stuff is redundant. C++11 makes it easier in that you don't need private, just = delete on the destructor. Explicitly declaring the destructor as deleted is preferable because it communicates to other programmers that you never intended to implement it. The way you have it, some programmer may initially think you just forgot to include the implementation.


You will want to declare both the default constructor and the destructor as deleted in order to protect against dynamic memory allocation (via new or placement new) because we otherwise won't get a compilation error because it's now on us to call delete or explicitly invoke the destructor. And if we conveniently forget, then things are fine:

Demo

class A
{
public:
    static bool foo(const char* filePath);
    static void foo(const int something);
    ~A() = delete;
};

int main(){
    A* a = new A(); // whoops I created an instance
    // we leak memory
}

Placement new demo

But deleting both the constructor and destructor prevents this:

Demo

class A
{
public:
    static bool foo(const char* filePath);
    static void foo(const int something);
    ~A() = delete;
    A() = delete;
};

int main(){
    A* a = new A(); // doesnt compile
    A b{}; // doesn't compile
    A c; // doesn't compile
}

refer to [class.dtor]: "A program is ill-formed if a destructor that is potentially invoked is deleted or not accessible from the context of the invocation."

Community
  • 1
  • 1
AndyG
  • 39,700
  • 8
  • 109
  • 143
1

No, it doesn't matter. You can make it deleted as well, but if the constructor is deleted, then deleting destructor will not do anything additional.

The first (deleted constructor) tells that it is not possible to create objects. The second (deleted destructor) tells that it is not possible to destroy objects.

Take a note that it is possible to "create" and initialize objects using various hacks, but in those cases all bets are off, and the program is executing undefined behavior.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • This answer is nearly correct. As I'm sure you've learned in the 3.5 yrs after you posted it :-) See my answer for more details – AndyG Aug 29 '18 at 16:02