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;
}
Related
As reported in this Q&A, const static member functions are/were not available in C++. Did anything change since then (2011)?
Is there another way to have static member functions that do not modify the static members of their class?
Something like (pseudo-code):
class C
{
static int a;
public:
static void Incr() { ++a; }
static int Ret() const { return a; }
};
int C::a = 0;
I would need to call a [const] static member function from another class' const member function.
According to the current cppreference.com (page about static members), static member functions still cannot be const, because the const keyword only modifies the this pointer, which static functions obviously do not have.
So nothing seems to have changed since the answer you were referring to was written.
Did anything change since then (2011)?
Nothing changed, you still can't cv-qualify a static member function.
Is there another way to have static member functions that do not modify the static members of their class?
Not a perfect solution, but you may declare const "aliases" to static data members:
static int Ret() {
static constexpr const auto& a = C::a;
// Now C::a is shadowed by the local a
// and the function can't modify it.
// a = 2; // ill-formed
return a * 2; // OK
}
It still requires discipline, but at least that way a compiler can catch unintended modification attempts.
Class which has only static fields and static methods doesn't deserve to be called class. It is just form of functions and global variables with fancy name spacing.
Anyway IMO it is much better to have a regular class with regular fields and methods and then instantiate it as a global variable (not very nice solution, but at least more honest where class contains only static fields and methods).
class C
{
int a;
public:
C() : a(0) {}
void Incr() { ++a; }
int Ret() const { return a; }
};
C instance;
Or use singleton pattern which I hate.
From generated code perspective there should be no difference.
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).
I have an object that is created in a .h file that should be initialised in the constructor. This object is passed a COM port number that is 5 in our current application. For this reason I have created a const int in the .h file.
Edit: I added a more complete example
class ClassB
{
public:
ClassB(int comPort);
private:
int m_comPort;
};
ClassB::ClassB(int comPort) :
m_comPort(comPort)
{
}
class ClassA
{
public:
ClassA();
private:
const int comPort;
ClassB B;
};
ClassA::ClassA() :
comPort(5),
B(comPort)
{
}
int main()
{
ClassA A;
return 0;
}
Because the object is initialised before comPort is fully initialised, the value for comPort is garbage.
What would be the correct way to circumvent this? I can think of the following:
Initialise the const int in the header file
Create and initialise the object in the body of the constructor
use a #define
It seems like a problem with the order your members are initialized. Class members are initialized in the order they are declared. The order they are initialized in the constructor does not override this. In the next example bar::my_foo is initialized before bar::my_const, which will cause problems. my_foo will be initialized with an unitialized my_const member;
struct foo {
foo(int p_x) : x(p_x) {}
int x;
}
struct bar {
bar() : my_const(5), my_foo(my_const) {}
foo my_foo;
const int my_const;
}
The problem can be fixed by changing order the members are declared.
struct bar {
bar() : my_const(5), my_foo(my_const) {}
const int my_const; // my_const before my_foo
foo my_foo;
}
You can reproduce your error if you exchange declaration of comPort and B in definition of ClassA. See this comment on SO concerning Constructor initialization-list evaluation order.
Hence, make sure that if an initializer list relies on a specific order of evaluation, then the declaration of the members to be initialized must adhere to this order.
Based on this question (asked a while ago)
inline-object-instantiation-and-transformation-in-java
Is there a way to instantiate and object and initialize it's members in a single line of c++, without the use of a constructor?
In java, as per the link:
JFrame aFrame = new JFrame();
aFrame.add(new JPanel() {{
setSize(100,100);
setLocation(50,50);
setBackground(Color.red);
}});
Can this be done in any way in c++?
EDIT: For example
class Foo{
public:
int test;
int test2;
};
int main(){
Foo foo(){{test=5 test2=4}}; //Like this
}
If the class is an aggregate (with no base classes, non-public members, virtual functions or user-declared constuctors), then you can use aggregate initialisation to initialise its members:
struct thing {
int a,b,c;
};
thing t = {1,2,3};
Otherwise, it can only be initialised by a constructor.
There's one idiom that allows syntax similar to Java. As with everything, it has its downsides as well. I'll leave it up to you to figure out whether it's right for this.
class Foo {
int a;
int b;
int c;
public:
Foo &setA(int val) {a = val; return *this;}
Foo &setB(int val) {b = val; return *this;}
Foo &setC(int val) {c = val; return *this;}
};
Now you can do the following:
auto foo = Foo().setB(2).setA(1).setC(3);
You can apply it to as many or few members as desired. However, it can be tricky in some cases to ensure you always have a valid object. Required initialization can go in the constructor.
Something along these lines that might be more natural is Boost.Parameter, which offers named parameter support that you can use to combine meaningful names with constructor arguments.
That is not an anonymous class. An anonymous class is one without a name.
If you want an anonymous (temporary) instance, and you can initialize it like so:
struct Foo {
int a;
int b;
};
void bar(Foo const &);
int main() {
bar(Foo{1,2});
}
See Mike's answer for the equivalent for a named instance of the named structure. The aggregate constraint is the same.
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.