I want to initialize array-of-classes member of a class
const int count = 5;
class In
{
float rate;
public:
In( int index )
{
rate = index / count;
}
};
class Out
{
In ins[count];
public:
Out() : /* ??? */
{
}
};
Can I obtain index of instance of In in initialization ins if I will rely on initialization list of Out::Out()
You can't do that. You need to define a default constructor for In.
Or better yet, use a std::vector.
EDIT: Might be supported in C++11, not sure though.
Related
I am writing a C++ struct which contains a C-struct. The C-struct is included by other .c files, so I cannot change it to C++.
I want to make sure that every member is of the c++ struct is initialized.
So I have used in-class initialization and constructor initilizer where needed:
struct CppStruct
{
CStruct pod {}; // initialize all members to 0
int i = 0;
double d = 0.0;
CppStruct()
{ }
CppStruct(int another_val)
: i(another_val)
{ }
};
This initializes all the members of the CStruct to zeroes.
Zeroes are fine for most members of the c-struct,
but unfortunately, it also contains a C-enum whithout a zero-value:
// C-header
enum Color { // no '0' entries here!
red = 1,
yellow = 2;
};
struct CStruct { // this struct can potentially contain a lot of members
int i;
int j;
Color col;
int m;
int n;
};
The only way I have found to write the constructor is this, but this theoretically sets the pod.col member twice:
CppStruct()
{ pod.col = Color::red; }
CppStruct(int another_val)
: i(another_val)
{ pod.col = Color::red; }
Is there anyway I can override the initialization of selected members of the pod, without having to specify all its members?
e.g. I tried this but it does not compile:
CppStruct() : pod.col(Color::red) {}
The following is legal, but I want to avoid it,
in case the CStruct is changed/shuffled by another colleague:
CppStruct() : pod{0,0,Color::red,0,0} {}
The best way I think is to just overwrite the col value inside the constructor, don't worry about multiple initializations, as it's just an enum, not a massive object, so the performance difference is somewhat nothing (unless you are really desperate for performance).
A quick and dirty way to achieve initialization the way you wanted is to create a static function that would return a default CStruct like that:
struct CppStruct
{
CStruct pod {}; // initialize all members to 0
int i = 0;
double d = 0.0;
CppStruct()
: pod(_get_default_pod())
{ }
CppStruct(int another_val)
: i(another_val), pod(_get_default_pod())
{ }
private:
static inline CStruct _get_default_pod() {
CStruct pod {};
pod.col = Color::red;
return pod;
};
};
How to store temporary state, needed for the initializer list, in the constructor (on the stack)?
For example, implementing this constructor …
// configabstraction.h
#include <istream>
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
int m_x;
int m_y;
int m_z;
};
… using a stateful helper class like this?
// mysillyparserdontworry.h
#include <json/reader.h> //jsoncpp
class MySillyParserDontWorry
{
public:
MySillyParserDontWorry(std::istream& input) { input >> m_parseTree; }
int intByName(const char* name) const { return m_parseTree[name].asInt(); }
private:
Json::Value m_parseTree;
};
My attempt:
// configabstraction.cpp
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: local_parserState(input) // init local variable first: Not possible!
, m_a(local_parserState.intByName("a"))
, m_b(local_parserState.intByName("b"))
, m_c(local_parserState.intByName("c"))
{
MySillyParserDontWorry local_parserState; // ...because it is local
}
With C++11 you could solve this with delegating constructors:
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
ConfigAbstraction(const MySillyParserDontWorry& parser);
int m_a;
int m_b;
int m_c;
};
ConfigAbstraction::ConfigAbstraction(const MySillyParserDontWorry& parser)
: m_a{parser.intByName("a")}
, m_b{parser.intByName("b")}
, m_c{parser.intByName("c")}
{
}
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: ConfigAbstraction{MySillyParserDontWorry{input}}
{
}
An alternative solution to your problem would be packing the three individual ints into a common data structure. This would allow you to initialise an object of that type with a private static helper function. Being able to initialise the object instead of assigning to it later also allows for it to be const (if that is required).
Here is an example with std::tuple. But you could also create your own helper struct or even std::array<int, 3>; the basic idea remains the same: have one member object instead of three.
#include <istream>
#include <tuple>
class MySillyParserDontWorry
{
public:
MySillyParserDontWorry(std::istream& input) { /* ... */ }
int intByName(const char* name) const { return /* ... */ 0; }
};
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
static std::tuple<int, int, int> parse(std::istream& input)
{
std::tuple<int, int, int> result;
MySillyParserDontWorry parser(input);
std::get<0>(result) = parser.intByName("a");
std::get<1>(result) = parser.intByName("b");
std::get<2>(result) = parser.intByName("c");
return result;
}
std::tuple<int, int, int> const m;
};
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: m(parse(input))
{
}
Why not simply doing the assignments in the constructor's body then?
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: m_a(0)
, m_b(0)
, m_c(0)
{
MySillyParserDontWorry local_parserState;
m_a = local_parserState.intByName("a");
m_b = local_parserState.intByName("b");
m_c = local_parserState.intByName("c");
}
Is there any specific requirement that hinders you doing that?
What an artificial limitation of C++!
It's not an artificial limitation. How should initialisation of local variables be done outside of their function's scope? It would just lead to a great confusion, where variables are actually initialised (naming conflicts aside).
You can not initialize local variables bedfore members. The reason for this is very simple (so that it is NOT an artificial limitation):
Members have to be initialized (constructed) before constructor body begins, because constructor body might access them - and they need to be initialized for this access. On the other hand, local variables do not exist before code enters constructor body (as for any other function).
Conclusion - initialization of local variables before members is impossible.
class ListOfGifts
{
private:
Gift list[50];
int count = 0;
public:
void suggest(ListOfGifts& affordable, float dollarLimit) const
{
// how do I initialize affordable to an empty list without a constructor
}
}
Trying to initialize a list from a parameter that is a reference. How can I do this?
Use an std::array:
class ListOfGifts
{
private:
std::array<Gift, 50> list;
int count = 0;
public:
void suggest(ListOfGifts& affordable, float dollarLimit) const
{
affordable.list = std::array<Gift, 50>{};
}
}
FYI, C++ is literally built on constructors. They will come up eventually, and they're actually quite helpful.
I use firstly boost::atomic class and there is a initialize problem.
I have a RowActiveData struct
struct RowActiveData {
RowActiveData() : _rowActive(0), _rowActiveFile(0), _rowActiveTrack(1)
{}
size_t _rowActive;
size_t _rowActiveFile;
size_t _rowActiveTrack;
};
and there is RowActive struct use it.
struct IRowActive {
virtual void setRowActive(size_t row) = 0;
};
struct RowActive : public IRowActive {
RowActive() {}
virtual void setRowActive(size_t row)
{
RowActiveData tmpData;
tmpData._rowActive = row;
tmpData._rowActiveFile = row * 2;
tmpData._rowActiveTrack = row * 3;
}
// boost::atomic
// <RowActiveData> _data;
RowActiveData _data;
};
When my process is run, I see everything is fine.
It gives me the values as I expected.
_rowActiveFile is 0 and _rowActiveTrack is 1.
But when I comment out
// RowActiveData _data;
and remove atomic comment out
boost::atomic <RowActiveData> _data;
it gives me garbage values.
What could be wrong?
According to the boost documentation, the empty constrcutor initializes to an unspecified value. Try
boost::atomic<RowActiveData> _data(RowActiveData());
Boost docs are at http://www.boost.org/doc/libs/1_54_0/doc/html/atomic/interface.html
Also, I've checked, and it seems to me that at least the boost implementation in http://www.chaoticmind.net/~hcb/projects/boost.atomic/ would use a char array member instead of RowActiveData, therefore not calling the constructor.
I have a constant value that never changes during run-time, but is impossible to know until run-time.
Is there a way to declare a constant (either as a member of a class or not) without defining it and also assign a computed value once (and only once) it is determined; or am I going to have to resort to a non-const declaration and use coding S & Ps (ALL_CAPS variables names, static declaration if in a class, etc.) to try and keep it from changing?
CLARIFICATION:
Though these are good answers, the real-world situation I have is more complicated:
The program has a main loop that continually runs between processing and rendering; the user can set required options and once they are set they will never change until the program is restart. An "Initialize" function is set up for anything that can be determined before the main loop, but values that are dependent on user interaction must be performed in the middle of the loop during the processing phase. (At the moment, persistent data storage techniques come to mind...)
Something like this?
const int x = calcConstant();
If it's a class member, then use the constructor initialisation list, as in Yuushi's answer.
You can define it in a struct or class and utilize an initialisation list:
#include <iostream>
struct has_const_member
{
const int x;
has_const_member(int x_)
: x(x_)
{ }
};
int main()
{
int foo = 0;
std::cin >> foo;
has_const_member h(foo);
std::cout << h.x << "\n";
return 0;
}
As a static or function-local variable:
const int x = calcConstant();
As a class member:
struct ConstContainer {
ConstContainer(int x) : x(x) {}
const int x;
};
Yes, you can make a private static singleton field with an initialization method and a gettor method. Here's an example of how to do it:
// In foo.h
class Foo
{
public:
// Caller must ensure that initializeGlobalValue
// was already called.
static int getGlobalValue() {
if (!initialized) {
... handle the error ...
}
return global_value;
}
static void initializeGlobalValue(...)
private:
static bool initialized;
static int global_value;
};
// In foo.cpp
bool Foo::initialized = false;
int Foo::global_value;
void Foo::initializeGlobalValue(...) {
if (initialized) {
...handle the error...
}
global_value = ...;
initialized = true;
}