1

I'm running a static analysis tool and getting an error because an abstract class, with no data members, has no constructors.

Given an abstract class with no data members:

class My_Interface
{
  public:
    virtual void interface_function(void) = 0;
};
  1. Are any constructors generated by the compiler?
  2. If a constructor is generated, what would it's content be?
  3. If a constructor is generated, would it be eliminated by an optimization level?

The rule documentation in the static analysis says:
If you do not write at least one constructor in a class, the compiler will write a public constructor for you by default. This rule detects if you do not declare at least one constructor.

The rule documentation references Scott Meyers, "Effective C++: 55 Specific Ways to Improve your Programs and Design", third edition.

My understanding is that the compiler will not generate constructors for the above case.

Edit 1:
This is not a duplicate of many constructor questions because:

  1. This one has no data members.
  2. This is not asking if a constructor is necessary, but what happens when a constructor is not provided.
  3. This is C++ language.
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • @DieterLücking: The destructor is not virtual, why should it appear in the vtable? Besides, the vtable should have one entry for `interface_function` – MSalters Jul 22 '15 at 18:38
  • @DieterLücking: Would the "optimizing away" occur at the "no optimization" (or Debug) setting? – Thomas Matthews Jul 22 '15 at 18:54

3 Answers3

1

The compiler at least theoretically synthesizes a constructor even in this case. Even though you can't create an instance of this class, the constructor will be invoked in the process of creating a derived class (that overrides interface_function, so it can be instantiated).

Given that this is basically a pure interface class, the constructor probably won't do anything, so most compilers will probably optimize it out (quite possibly even when you don't tell it to optimize the code).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • So to eliminate generation of the constructor, should I use the idiom of declaring private constructors and destructors? – Thomas Matthews Jul 22 '15 at 18:44
  • @ThomasMatthews: if you declare the constructor/destructor private, the compiler *shouldn't* allow you to instantiate objects of a derived class, unless you declare it a friend to give it access to those private members. In many cases, however, this is purely theoretical--by default, many compilers don't enforce access restrictions on elided members. – Jerry Coffin Jul 22 '15 at 18:47
  • @JerryCoffin: What exactly are those cases? Which compiler would not generate a diagnostic for `class Base { private: Base() {} }; class Derived : public Base {}; int main() { Derived d; }`? – Christian Hackl Jul 22 '15 at 19:14
  • @ChristianHackl: I probably worded things poorly. I'm not sure any compiler has ever let that specific case by, but at least some older compilers have been lax about vaguely similar restrictions. I wasn't trying to say: "your compiler will probably allow this even though it's not legal" nearly as much as: "avoid this, even if your compiler doesn't stop you from doing it." – Jerry Coffin Jul 22 '15 at 19:46
0
  1. Are any constructors generated by the compiler?

Yes. Several. First, from [class.ctor]:

A default constructor for a class X is a constructor of class X that either has no parameters or else each parameter that is not a function parameter pack has a default argument. If there is no user-declared constructor for class X, a non-explicit constructor having no parameters is implicitly declared as defaulted (8.4). An implicitly-declared default constructor is an inline public member of its class. A defaulted default constructor for class X is defined as deleted if:

Several bullet points follow, none of which apply. So we have the equivalent of:

My_Interface() = default;

Then, from [class.copy]:

If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4).

So we have:

My_Interface(const My_Interface&) = default;

Also:

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.

So we also have:

My_Interface(My_Interface&& ) = default;
  1. If a constructor is generated, what would it's content be?

All three are generated, all three are = default;

  1. If a constructor is generated, would it be eliminated by an optimization level?

None of the three constructors are trivial because My_Interface has a virtual function. As such, at the very least, the vtable will need to be initialized/copied. So something will have to happen, even if there aren't any members to initialize/copy/move.

Barry
  • 286,269
  • 29
  • 621
  • 977
0

Q1. Are any constructors generated by the compiler?

Answer: Yes. From the C++11 Standard:

12.1 Constructors

5 A default constructor for a class X is a constructor of class X that can be called without an argument. If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted (8.4). An implicitly-declared default constructor is an inline public member of its class.

I don't see anything in the standard that answers the other two questions. However, in your case, since there is a virtual member function, the default constructor must, at least, set the virtual table of the object.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1) Is this still valid for versions prior to C++11? 2) My understanding is a virtual table is not required. – Thomas Matthews Jul 22 '15 at 19:03
  • @ThomasMatthews: Virtual tables are an implementation concept, not a language concept. The standard does not mention them. – Christian Hackl Jul 22 '15 at 19:15
  • @ThomasMatthews, I don't have access to the C++03 standards. I am going to guess that the answer to your question is "yes". It make sense to me that the compiler generate a default constructor. A virtual table is definitely required. How can dynamic dispatch be accomplished without that? – R Sahu Jul 22 '15 at 19:16