In the following fragment of code I receive a compiler error when the method Data::setValue(int, int) is declared virtual:
struct Data{
int ma;
int mb;
virtual void setValues(int a, int b){
ma = a;
mb = b;
}
};
struct ThreadMessage {
enum type {
DATA
};
type msg_type;
union content {
Data d;
int a;
}content;
};
The error that the compiler (g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3) gives me is:
struct.cpp:19:14: error: member 'Data ThreadMessage::content::d' with
constructor not allowed in union
struct.cpp:19:14: error: member 'Data ThreadMessage::content::d' with copy assignment operator not allowed in union
This set of compiler errors took me completely off guard. In the actual code, I had many more attributes and functions. Therefore, I started looking where I put the bloody operator=() and constructor but I didn't write them in struct Data.
I know my problem disappears when I make the Data::setValues as not virtual. But why does the struct Data have a constructor? When exactly does a struct have a constructor in C++? And why does the compilation error disappear when I make virtual void Data::setValues(int, int) non virtual?
Barring the default access of members, a struct and a class are identical in C++.
Unless you program carefully (and have C++11), you cannot have a class or a struct member in a union since there would be ambiguity as to how such members of the union should be constructed.
That's what your compiler is telling you.
You may want to browse through this thread: Struct Constructor in C++?
The Reader's Digest version is that, like classes, structs have a default constructor, which you can overload and define however you like.
The error messages you quoted are misleading, so no doubt you wonder why making the function non-virtual fixes the problem.
First - structs and classes in C++ have constructors and copy assignment operators. If you do not create them yourself, they will be created for you. (You may delete those default versions). In your example there is an automatically generated constructor of Data, and also automatically generated assignment operator.
Now why the error messages are misleading? Because they are not true. In C++ you can have union members with constructors or assignment operators. The problem starts when those member functions are not trivial. Before C++11 it was just not possible to have an union member with non-trivial constructor. C++11 changed it, but still without writing additional functions it is not possible to use such union.
A struct/class with virtual functions has non-trivial member functions as constructor and assignment operator (because hidden data member needs to be managed). This is why when you make the function non-virtual the errors disappear - then the member functions become trivial and your struct may be used as a union member without problems.
When exactly does a struct have a constructor in c++
Always.
The error message is a bit confusing, but it's saying that you cannot have a class there.
A class is a type defined with either the struct keyword or the class keyword.
Every class has a constructor and an assignment operator, whether it's user-provided or not.
The compiler error message is a bit misleading. From the conceptual language point of view your class Data will have a constructor in any case, regardless of whether the function is virtual or not.
The compiler is apparently a pre-C++11 one (or works in pre-C++11 mode). And it does not like the fact that Data's constructor is non-trivial. It is specifically the non-triviality of Data's constructor that makes the compiler to say that Data is a class "with constructor".
In this particular case the constructor becomes non-trivial once you introduce at least one virtual function into the class.
A non-trivial constructor is a constructor that has to do something (in your case - initialize the per-object household information that support polymorphism). I.e. it is a constructor that must exist physically in generated code. Meanwhile a trivial constructor exists only conceptually, but produces no code. The compiler is referring to that physical distinction when it separates classes into ones "with constructor" and ones "without constructor".
Related
Let's say I've defined a class containing some simple POD members, and I was too lazy to write out a default constructor to init all the class members to default values. Instead, I asked the compiler to do that for me:
class Foo
{
public:
Foo() = default;
int x;
// etc.
}
I've tested with MSVC, and x is not initialized to zero by this auto-generated constructor: for a local object of class Foo, x was set to 0xcccccccc, which is the value I'd expect for an uninitialized stack variable.
My question is whether there is a standards-compliant way to convince the compiler to zero-init these POD members automatically. I say "standards compliant" because I need to be able to rely on other compilers to behave similarly. And I say "automatically" because I don't want to have to write out a constructor that lists every class member if I can avoid it.
You can use in-class member initializers like this:
class Foo {
int x = 0;;
int y{}; // same effect.
};
The advantage is consistency across constructors that are possibly added later on. This approach is also recommended by the Core Guidelines C.45.
A disadvantage can arise when such a class is declared in a header file, because the type of all member variables that are initialized that way must be known and can't be forward-declared.
Their are two solutions:
Either define a default initializer of the members as in the answer of lubgr which just showed up.
Or always prefer to value initialize your class instances where you could default initialize them: Foo an_obj{}; in place of Foo an_obj;.
I have read that the default constructor performs no action(The default constructor for class T is trivial (i.e. performs no action) if some conditions are true and those condition are true I guess when implicitly defined. http://en.cppreference.com/w/cpp/language/default_constructor
So if it performs no action, why is it even added by the compiler and why is it required for classes?
Thanks!
It purpose is to bring object to life if there is no suitable constructor available
Example:
struct Foo{};
struct Bar
{
Bar() = delete; // no default constructor
};
int main()
{
Foo f;
// Bar b; // does not compile
}
The CRT calls the constructor when a class is instantiated, so therefore one must exist for it to call, even if it does "nothing." The compiler generates a default constructor for you if one is not provided for that reason. Otherwise, there would be no way to instantiate the object. The rules, steps, and order of things that happen at construction time is simply part of the language.
Even if the body is empty, it is still at construction time that a class' data members are initialized.
Also, consider what occurs if the class is derived from another, at construction time.
See http://isocpp.org/wiki/faq/ctors#overview-ctors for an in depth look at the topic of constructors.
Because the compiler will only generate a default constructor when it needs to be called. This could be by a derived class or a standard library container, for example. The compiler is still free to optimise it away as it is with an explicitly defined do nothing function.
How can I prohibit the construction of an object? I mark = delete; all relevant special functions as follows:
struct A
{
A() = delete;
A(A const &) = delete;
A(A &&) = delete;
void * operator new(std::size_t) = delete;
void operator delete(void *) = delete;
};
A x{};
A y = {};
A * z = ::new A{};
LIVE EXAMPLE
But x, y and *z can still exist. What to do? I am interested in both cases; static/stack allocation and heap allocation.
One option would be to give the class a pure virtual function, and mark it final:
struct A final
{
virtual void nonconstructible() = 0;
};
[Live example]
If you want to have just static members, then write namespace A rather than struct A. Ensuing code will be syntactically similar.
To prevent creation of an instance of a class, make it abstract. (Include one pure virtual function). But doing this introduces a v-table into you class, which you might not want.
If you want to make it impossible to instantiate the class you could just declare private constructors:
class NotInstantiable {
private:
NotInstatiable();
public:
};
And not defining NotInstantiable further. This can't now be instantiated since first the constructor is private but also that a definition for the constructor has not been provided.
The second obstacle for instantiate the NotInstantiable would for example prohibit this possibility, which in fact otherwise is a well known pattern:
class NotInstantiable {
private:
NotInstantiable();
public:
NotInstantiable* evil_method()
{
return new NotInstantiable(); // this will fail if there's no body of the constructor.
}
};
In general, to completely prevent client code instantiation of a class you can declare the class final and either
make the constructors non-public, or
delete the constructors and make sure that the class isn't an aggregate, or
add a pure virtual member function (e.g. make the destructor pure virtual) to make the class abstract.
Declaring the class final is necessary when the non-public is protected, and for the abstract class, in order to prevent instantiation of a base class sub-object of a derived class.
To partially prohibit instantiation, you can
make the destructor non-public.
This prevents automatic and static variables, but it does not prevent dynamic allocation with new.
make the class' allocation function (the operator new) non-public.
This prevents dynamic allocation via an ordinary new-expression in client code, but it does not provide automatic and static variables, or sub-objects of other objects, and it does not prevent dynamic allocation via a ::new-expression, which uses the global allocation function.
There are also other relevant techniques, such as an allocation function with extra arguments that make new-expressions inordinately complicated and impractical. I used that once to force the use of a special macro to dynamically allocate objects, e.g. for a shared-from-this class. But that was in the time before C++11 support for forwarding of arguments; nowadays an ordinary function can do the job, and such a function can be made a friend of the class.
The fact that the code compiles with at least one version of the clang compiler with -std=gnu++1z, is due to a bug and/or language extension in that compiler.
The code should not compile, since it invokes the default constructor that has been deleted. And it does not compile with e.g. MinGW g++ 5.1.0, even with -std=gnu++1z.
The fact that the code compiles with at least one version of the clang compiler with -std=gnu++1z, may be due to a bug and/or language extension in that compiler. What the correct behavior is, is unclear because
Although the code compiles with clang and with Visual C++ 2015, it does not compile with e.g. MinGW g++ 5.1.0, even with -std=gnu++1z.
Intuitively the delete would be meaningless if the code should compile, but many meaningless constructs are permitted in C++.
At issue is whether the class is an aggregate (in which case the new expression performs aggregate initialization), which rests on whether the deleted default constructor can be regarded as user-provided. And as user TartanLlama explains in comments, the requirements for user-provided are
C++11 §8.4.2/4
” A special member function is user-provided if it is user-declared and not explicitly
defaulted or deleted on its first declaration.
I.e. although the delete of the default constructor in this question's example declares that constructor, it's not user-provided (and ditto for the other members) and so the class is an aggregate.
The only defect report I can find about this wording is DR 1355, which however just concerns an issue with the use of the words “special member”, and proposes to drop those words. But, considering both the effect demonstrated by this question, and considering that a function can only be deleted on its first declaration, the wording is strange.
Summing up, formally, as of C++11 (I haven't checked C++14), the code should compile. But this may be a defect in the standard, with the wording not reflecting the intent. And since MinGW g++ 5.1.0 doesn't compile the code, as of October 2015 it's not a good idea to rely on the code compiling.
Essentially this compiles and is allowed because the type A is an aggregate type and the aggregate initialisation doesn't use default constructors.
What is an aggregate type?;
class type (typically, struct or union), that has
no private or protected members
no user-provided constructors (explicitly defaulted or deleted constructors are allowed) (since C++11)
no base classes
no virtual member functions
Giving it any one of the above would make it non-aggregate and thus the aggregate initialisation would not apply. Giving it a private user defined (and unimplemented) constructor will do.
struct A
{
A() = delete;
A(A const &) = delete;
A(A &&) = delete;
void * operator new(std::size_t) = delete;
void operator delete(void *) = delete;
private:
A(int);
};
As a side note; I hope this is a defect in the language specifications. At first look I thought that this should not compile, yet it does. One of the motivations for the =delete was to avoid the C++03 "trick" of declaring the constructors private to "hide" them and thus be unusable. I would expect a =delete on the default constructor to effectively prohibit class creation (outside other user defined constructors).
For easier reading and clearer intent, consider even an empty base class;
struct NonAggregate{};
struct A : private NonAggregate
{
//...
Maybe the simplest yet is to return to the C++03 style here, make the default constructor private;
struct A
{
private:
A(); // note no =delete...
};
I am working on an application which in my opinion is rather poorly designed but that's another issue. There is a simple class in that app that I need to add a variable to. In this case I would like to add a STL stack to the class. Should be simple except that elsewhere the same class is used within a union and the compiler then complains that the class has a copy constructor. If I remove my added variable it compiles fine. My first thought was to add the stack as a pointer and then initialise it in the constructor but then the compiler complains that the class has a non trivial constructor.
My second (not ideal) thought was to add it as a pointer and initialise it outside the class. I know this isn't a good solution but I am up against some poorly designed code here which I cannot rewrite. However, this won't work because where I would need to initialise it, I cannot know if it has already been initialised or not. I cannot initialise the pointer in the class to NULL as even just doing that makes the compiler complain that the class now has a non-trivial constructor.
I guess my question is two-fold. Is there a way of adding a STL stack to a class that is used in a union? If not, is there a way of initialising a pointer to NULL in a class that is used in a union?
The class and union look something like this:
class MyClass
{
public:
std::stack<short> Index; // ideally what I wanted
}
union
{
int nNum;
MyClass myclass;
} u;
Please note: I cannot change the union. I accept that I cannot do what I was thinking. Is there any alternative no matter how silly it might sound. I cannot change the union or redesign the app as much as I would like to. This is the problem when you work on large apps that were first written around 18 years ago.
You could define the union as
union
{
int nNum;
MyClass * myclass;
} u;
This has the added benefit that int and pointer are the same size and it compiles.
Also, your example won't compile. It's missing ';' at the end of the class.
The answer for both questions is NO for C++03.
Since
9.5 Unions [class.union]
1
...
An object of a class with a non-trivial default constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor (12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor
can an array of such objects. If a union contains a static data member, or a member of reference type,
the program is ill-formed.
You still can add constructor to the union that will init pointer instead of class ctor.
In C++11 however you can provide your own constructors for union, that should implement correct way to copy classes with non trivial constructors.
9.5 Unions [class.union]
2 A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class. If a union contains a non-static data member of reference type the program is ill-formed. At most one non-static data member of a union may have a brace-or-equal-initializer. [Note: If any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union. — end note ]
You may also be interested in a following article
http://cpp11standard.blogspot.com/2012/11/c11-standard-explained-1-unrestricted.html
class Foo {
Foo(int val) { /* Do some initialization */ }
Foo() { /* Do nothing */ }
};
union Bar {
Foo foo;
};
That code generates this error:
error C2620: member 'Bar::foo' of union 'Bar' has user-defined constructor or non-trivial default constructor
I understand why you'd throw that error if the constructor actually did something, but the constructor here takes no parameters and does nothing. Is there any way I can stuff this class into a union? I've had to resort all the way to doing char foo[sizeof(Foo)] and would like a cleaner solution.
Originally from this question:
Initializing a union with a non-trivial constructor:
From C++03, 9.5 Unions, pg 162
A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class.An object of a class with a non-trivial constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor (12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor can an array of such objects
So, your class is forbidden to be a member of the union.
This isn't allowed in the C++03 standard.
If objects with user defined default constructors were allowed in a union, the compiler couldn't decide which constructor to use, because all refer to the same memory location. Thus, objects with user defined constructors aren't allowed in unions.
The compiler will ignore the fact that your constructor doesn't do anything, because it might be defined elsewhere than the union.
You might get away with a C++0x constructor() = default;
Standard-specialists will likely answer this question more precisely than I do, but if I recall correctly, union members must be of POD type.
Use boost::variant if you want to use non-POD classes inside a union.
If your class has a user defined constructor, destructor or copy constructor, or assignment operator then it cannot be inside of a Union.