I am using the default constructor as an example here, but the same question applies to all the special member functions.
Also, I am using https://en.cppreference.com instead of the standard because that is what I am reading and that is what I am having trouble understanding. If using the standard would change the question in any way, please let me know.
As stated in https://en.cppreference.com/w/cpp/language/default_constructor, if a class has no constructor then the compiler will always declare a default one. Then, if certain conditions aren't met, it will be undefined (pre c++11) or defined as deleted (post c++11).
All this seems to imply that there is a difference between a function being not declared, declared but not defined, or declared and deleted. However, all three options won't compile/link, e.g.
class MyClass {
public:
void foo();
void bar() = delete;
};
int main() {
MyClass c;
//c.foo(); // won't link
//c.bar(); // won't compile
//c.baz(); // won't compile
}
So why is it so important to change the definition from "declared and undefined" to "declared and deleted", and why not just leave it as "undeclared" in the first place?
So why is it so important to change the definition from "declared and undefined" to "declared and deleted"
Because of the difference: "won't link" vs "won't compile". This is a fundamental reason for why = delete
was introduced: To catch the bugs of using (previously) undefined functions at compile time, rather than later. Furthermore, it allows better error diagnostic, since the compiler will be able to describe why the function is deleted. The best that the linker can say is that nobody defined it for some unknown reason.
There's no reason not to take advantage of the feature with the implicitly generated member functions.
The = deleted;
declaration can be useful in various situations. As well as the very good reason given by eerorika, it can also be used to explicitly declare that a given 'special' function, such as the default constructor doesn't exist, and cannot be called.
It can also be used to specify that a function which exists in a base class does not exist in a derived class (which, by default, it will).
Here's a short piece of code showing such usage:
#include <iostream>
class foo {
private:
int m;
public:
foo() = delete; // Other programmers reading this definition will know immediately!
foo(int n) : m{ n } {} // ... that default ctor is intended not to be used
void inc() { ++m; } // ... rather than it has been omitted accidentally
int get() { return m; }
};
class bar : public foo {
public:
bar() : foo(0) {}
void inc() = delete; // Without this, code like `bar b; b.inc();` will call foo.inc()
};
int main() {
// foo f1; // error C2280: 'foo::foo(void)': attempting to reference a deleted function
foo f2(3); std::cout << f2.get() << std::endl;
f2.inc(); std::cout << f2.get() << std::endl;
bar b1; std::cout << b1.get() << std::endl;
// b1.inc(); error C2280: 'void bar::inc(void)': attempting to reference a deleted function
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With