7

Is there any way to create base class (such as boost::noncopyable) and inherit from it, which will forbid compiler to generate default constructor for derived classes, if it wasn't made by user (developer)?

Example:

class SuperDad {
XXX:
  SuperDad(); // = delete?
};

class Child : YYY SuperDad {
public:
  Child(int a) {...}
};

And result:

int main () {
  Child a;     // compile error
  Child b[7];  // compile error
  Child c(13); // OK
}
Trollliar
  • 826
  • 5
  • 14
  • 2
    make it private. See this question http://stackoverflow.com/questions/10474417/how-to-delete-the-default-constructor – RAEC Aug 06 '15 at 18:20
  • It really works. Great thanks! It was really difficult to understand inheritance level and modifiers combination to make this works properly. – Trollliar Aug 06 '15 at 18:20
  • EDITED: it was an answer to previous disappeared comment. – Trollliar Aug 06 '15 at 18:26
  • @RAEC, this way will deprecate inheritance at all, see [this topic](http://stackoverflow.com/questions/2184133/prevent-class-inheritance-in-c) – Trollliar Aug 06 '15 at 18:28
  • he can still declare his constructor with one parameter and make it public, by the way in C++11 you can actually "delete" the constuctor http://en.cppreference.com/w/cpp/language/default_constructor `ClassName() = delete ;` – RAEC Aug 06 '15 at 18:38
  • @RAEC, deleted default constructor will cause compile error: "use of deleted function `Base::Base()`" while creating Child or Base objects (kind of approach for "static" class creating). See [topic](http://stackoverflow.com/questions/13654927/why-explicitly-delete-the-constructor) – Trollliar Aug 06 '15 at 18:47
  • that is only if the child process does not make use of the parameterized constructor; see my answer below, i posted it as answer cuz i dont know how to post the code pretty in this comment lol – RAEC Aug 06 '15 at 18:55

3 Answers3

6

Make the constructor private.

protected:
    Base() = default;
Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
Trollliar
  • 826
  • 5
  • 14
  • Yea, thanks. Answer "make it private" was not completely clear at fist (@RAEC), because **private** modificator does pretty other thing. – Trollliar Aug 06 '15 at 18:39
  • According to the fair comment by [Tomasz Sodzawiczny](http://stackoverflow.com/a/31876240/1880175), the code from example above **will compile** until user defines his own non-trivial constructor for Child, if we use this approach. – Trollliar Aug 07 '15 at 11:34
4
#include <iostream>
using namespace std;


class InterfaceA
{
public:

InterfaceA(std::string message)
{
    std::cout << "Message from InterfaceA: " << message << std::endl;
}

private:
    InterfaceA() = delete;
};


class MyClass: InterfaceA
{
public:
    MyClass(std::string msg) : InterfaceA(msg)
    {
        std::cout << "Message from MyClass: " << msg << std::endl;
    }
};

int main()
{
    MyClass c("Hello Stack Overflow");
    return 0;
}
RAEC
  • 332
  • 1
  • 8
  • It's work, but you should declare public constructor with parameter in base class. Previous answer is more elegant and pretty compact, isn't it? :) Moreover, with this approach you can create **InterfaceA** object, which can be questionable. – Trollliar Aug 06 '15 at 19:05
  • he specifically said he wanted to "Forbid using default constructor in derived classes, C++" lol setting the default to the already default constructor does not help on that one. in the previous answer he can still inherit from it and use the default constructor. But its good to have diverse answers, he just acquired more knowledge than he thought he would probably haha – RAEC Aug 06 '15 at 19:10
  • Yeah, of course, that's nice, thanks you (I already "+" your answer), and it's my question in topic :) – Trollliar Aug 06 '15 at 19:17
  • oh wow, i just realized that you were the one that asked the question, geez, sorry lol i would have probably provided you with the code and better answers before, but i thought it was someone else discussing this with me :/ sorry; hope all this helped you anyway haha – RAEC Aug 06 '15 at 19:19
1

According to this cppreference.com article (which is basically a lawyer-to-human translation of C++ standard 12.1. section):

If no user-defined constructors of any kind are provided for a class type (struct, class, or union), the compiler will always declare a default constructor as an inline public member of its class.

The only way you can control the implicitly defined constructor of Child from SuperDad is making the compiler to define it as deleted.

You can do that by making the default constructor (or destructor) of SuperDad deleted, ambiguous or inaccessible - but then you have to define some other way to create the base class and use it implicitly from all the child constructors.

  • it will compile until user defines own Child non-trivial constructor (with arguments). So, in this case, Ben's answer is correct in context of my topic question. If I want to control creating Child's, I should understand cases of their usages and define at least one non-trivial constructor according to necessary logic. – Trollliar Aug 07 '15 at 11:27
  • In my understanding Ben's answer changes base class behaviour only (can't be directly instantiated), while not changing a thing about the derived class. – Tomasz Sodzawiczny Aug 07 '15 at 11:58
  • The point was to prevent default construction of Child by user (actually, the Child classes are kind of API) and wrong usages, so making base constructor private really affects Child behavior. Of course, there may be several interpretations of my question, cause I did not formulate it precisely enough. – Trollliar Aug 07 '15 at 12:16