I have a class which is used in a union, and therefore cannot have a (non-trivial) constructor. I need to create a const instance of the class, can this be done?
i.e.:
class Foo {
// no constructors...
private:
int i;
};
union {
Foo foo;
Bar bar;
} FooBar;
const Foo defaultFoo = ???
Yes, you can copy-construct it from the result of a function:
static Foo configureDefaultFoo()
{
Foo f; // not const
f.setI(42); // call non-const member functions
return f;
}
const Foo defaultFoo = configureDefaultFoo();
Note that although this results in an object that is const, it is dynamic initialization not static, and so it can suffer from the static initialization order fiasco (same would be true if calling a non-trivial constructor, only aggregate initialization would avoid the fiasco).
Related
Say I have
class A {
public:
A();
A(int);
static const int foo;
int bar;
}
how do I go about constructing the class if I want the static member to be initialised in the constructor? This:
A::A()
{
foo = 123;
bar = 42;
}
A::A(int b)
{
foo = 123;
bar = b;
}
seems to work, but if the static member foo is shared among all the instances of the class, how is it that I can initialise it twice? It just seems like I'm doing something wrong.
Well, yes you are doing something wrong …
first off, a static const member should to be initialized directly in the class declaration (because it is const as mentioned in some comments, it can but does not 'need' to be).
But generally speaking, if you have a static class member, you can simply provide an initializer as a forward definition like so:
int A::foo = 42;
This allows the compiler to init the static member before any of your constructors are even called. (This is handled for you by the standard C++ library).
If you have a static member that is not const, you can change it anywhere you like, including "in the constructor". It may not make much sense to do so (especially in a constructor that is very strongly coupled to a given class instance), but it's possible.
If the static member is const (as in your code), you cannot change it anywhere. You can only initialize it (once). You can either do this directly with the declaration (const static int foo = 42) or in the corresponding .cpp file (const int A::foo = 42).
For C++11:
A static variable has to be defined outside the class in you cpp file, if it can't be initialized with an initializer in which every expression is a constant expression, right inside the class definition:
file.h
class A {
public:
A();
A(int);
static const int foo;
int bar;
}
file.cpp
const int A::foo = 123;
For C++17:
This can be done inlined.
class A {
public:
A();
A(int);
inline static const int foo = 123;
int bar;
}
I have C++ code that boils down to something like the following:
class Foo{
bool bar;
bool baz;
Foo(const void*);
};
Foo::Foo(const void* ptr){
const struct my_struct* s = complex_method(ptr);
bar = calculate_bar(s);
baz = calculate_baz(s);
}
Semantically, the bar and baz member variables should be const, since they should not change after initialization. However, it seems that in order to make them so, I would need to initialize them in an initialization list rather than assign them. To be clear, I understand why I need to do this. The problem is, I can't seem to find any way to convert the code into an initialization list without doing one of the following undesirable things:
Call complex_method twice (would be bad for performance)
Add the pointer to the Foo class (would make the class size needlessly large)
Is there any way to make the variables const while avoiding these undesirable situations?
If you can afford a C++11 compiler, consider delegating constructors:
class Foo
{
// ...
bool const bar;
bool const baz;
Foo(void const*);
// ...
Foo(my_struct const* s); // Possibly private
};
Foo::Foo(void const* ptr)
: Foo{complex_method(ptr)}
{
}
// ...
Foo::Foo(my_struct const* s)
: bar{calculate_bar(s)}
, baz{calculate_baz(s)}
{
}
As a general advice, be careful declaring your data members as const, because this makes your class impossible to copy-assign and move-assign. If your class is supposed to be used with value semantics, those operations become desirable. If that's not the case, you can disregard this note.
One option is a C++11 delegating constructor, as discussed in other answers. The C++03-compatible method is to use a subobject:
class Foo{
struct subobject {
const bool bar;
const bool baz;
subobject(const struct my_struct* s)
: bar(calculate_bar(s))
, baz(calculate_baz(s))
{}
} subobject;
Foo(const void*);
};
Foo::Foo(const void* ptr)
: subobject(complex_method(ptr))
{}
You can make bar and baz const, or make the subobject const, or both.
If you make only subobject const, then you can calculate complex_method and assign to bar and baz within the constructor of subobject:
class Foo{
const struct subobject {
bool bar;
bool baz;
subobject(const void*);
} subobject;
Foo(const void*);
};
Foo::Foo(const void* ptr)
: subobject(ptr)
{}
Foo::subobject::subobject(const void* ptr){
const struct my_struct* s = complex_method(ptr);
bar = calculate_bar(s);
baz = calculate_baz(s);
}
The reason that you can't mutate const members within a constructor body is that a constructor body is treated just like any other member function body, for consistency. Note that you can move code from a constructor into a member function for refactoring, and the factored-out member function doesn't need any special treatment.
You may use delegate constructor in C++11:
class Foo{
public:
Foo(const void* ptr) : Foo(complex_method(ptr)) {}
private:
Foo(const my_struct* s) : bar(calculate_bar(s)), baz(calculate_baz(s)) {}
private:
const bool bar;
const bool baz;
};
If you don't want to use the newfangled delegating constructors (I still have to deal with compiler versions that don't know about them), and you don't want to change the layout of your class, you could opt for a solution that replaces the constructor with const void * argument by a static member function returning Foo, while having a private constructor that takes the output from complex_method as argument (that latter much like the delegating constructor examples). The static member function then does the necessary preliminary computation involving complex_method, and ends with return Foo(s);. This does require that the class have an accessible copy constructor, even though its call (in the return statement) can most probably be elided.
My c++ book says this (lippman, c++ primer, fifth ed., p. 508):
The synthesized default constructor is defined as deleted if the class ... has a const member whose type does not explicitly define a default constructor and that member does not have an in-class initializer. (emphesis mine)
Why then does this code produce an error?
class Foo {
Foo() { }
};
class Bar {
private:
const Foo foo;
};
int main() {
Bar f; //error: call to implicitly-deleted default constructor of 'Bar'
return 0;
}
The rule above seems to indicate that it should not be an error, because Foo does explicitly define a default constructor. Any ideas?
To fix your error. You need to make Foo::Foo() public.
class Foo
{
public:
Foo() { }
};
Otherwise I do believe it is private.
Is this what your looking for?
The default constructor is omitted when a a class construction isn't trivial.
That in general means that either there is an explicit constructor that receives parameters (and then you can't assume that it can be constructed without those parameters)
Or if one of the members or base classes need to be initiated in construction (They themselves don't have a trivial constructor)
I think that this should work
class Foo {
public:
Foo() { }
};
class Bar {
public:
Bar() : foo() {}
private:
const Foo foo;
};
What's the diference between use:
static Foo foo;
// ...
foo.func();
And:
Foo& GetFoo(void)
{
static Foo foo;
return foo;
}
// ...
GetFoo().func();
Which is better?
The principal difference is when construction occurs. In the first case, it occurs sometime before main() begins. In the second case, it occurs during the first call to GetFoo().
It is possible, in the first case, for code to (illegally) use foo prior to its initialization. That is not possible in the second case.
A GetFoo is generally used when you don't want copies of your class/object.
For example:
class Foo
{
private:
Foo(){};
~Foo();
public:
static Foo* GetFoo(void)
{
static Foo foo;
return &foo;
}
int singleobject;
};
You can externally access singleobject via Foo::GetFoo()->sinlgeobject. The private constructors and destructors avoid your class getting copies created.
For the use of static Foo foo, you must have public constructors declared which means you are always accessing your class by it, but your class will also be able to get copies.
Why do we declare constructor's as public?
Constructors are the way objects are created. If your constructor were not public, then it couldn't be used to construct a new object from outside the class.
Note that sometimes a non-public constructor is useful, for example:
class foo
{
public:
static foo make_foo(int i)
{
// only functions of foo can use that constructor,
// because it's private; return a foo
return foo(i);
}
private:
foo(int i) { /* construct */ }
};
Now foo can only be created via the function make_foo, for whatever reason.
In the below code line, initialization should take place via constructor. If the constructor is private in this case, how is it going to be accessed outside the class scope. Moreover, foo::foo(int num) is going to be called by default while instantiation of obj.
foo *obj = new foo(5);
If you don't you will not be able to construct the object from other objects.