Intitialzing an array in a C++ class and modifiable lvalue problem - c++

I have a basic C++ class .The header looks like this:
#pragma once
class DataContainer
{
public:
DataContainer(void);
~DataContainer(void);
int* getAgeGroup(void);
int _ageGroupArray[5];
private:
int _ageIndex;
};
Now inside the cpp file of the class I want to intialize the _ageGroupArray[5] with default values inside the class contructor like this:
#include "DataContainer.h"
DataContainer::DataContainer(void)
{
_ageGroupArray={20,32,56,43,72};
_ageIndex=10;
}
int* DataContainer::getAgeGroup(void){
return _ageGroupArray;
}
DataContainer::~DataContainer(void)
{
}
Doing it I am getting "Expression must be a modifiable lvalue" on _ageGroupArray line.So is it entirely impossible to initialize an array object in the constructor? The only solution I found was to define the array outside scope identifiers .Any clarification on this will be greatly appreciated.

In the current standard, as you have already noticed, you cannot initialize a member array in the constructor with the initializer list syntax. There are some workarounds, but none of them is really pretty:
// define as a (private) static const in the class
const int DataContainer::_age_array_size = 5;
DataContainer::DataContainer() : _ageIndex(10) {
int tmp[_age_array_size] = {20,32,56,43,72};
std::copy( tmp, tmp+_age_array_size, _ageGroupArray );
}
If the values in the array are always the same (for all object in the class) then you can create a single static copy of it:
class DataContainer {
static const int _ageGroupArraySize = 5;
static const int _ageGroupArray[ _ageGroupArraySize ];
// ...
};
// Inside the cpp file:
const int DataContainer::_ageGroupArray[_ageGroupArraySize] = {20,32,56,43,72};

You can Initialize a array when you Create/Declare it, not after that.
You can do it this way in constructor :
_ageGroupArray[0]=20;
_ageGroupArray[1]=32;
_ageGroupArray[2]=56;
_ageGroupArray[3]=43;
_ageGroupArray[4]=72;
It is important to know that this is Assignment & not Initialization.

try this:
int ageDefault[]={20,32,56,43,72};
memcpy(_ageGroupArray, ageDefault, sizeof(ageDefault));

Related

Declare size of a vector inside class

I am trying to declare the size of a vector inside a class. I want the vector size equal to another attribute of this same class. Vector "table" is inside the class Hashtable. "bucket_count" is the intended size for the vector "table". the error given is "member is not a type name". Please let me know what another way I can declare the size of a vector inside the class. If not, then what is the way out? Thanks.
Please refer to the code below.
class HashTable {
public:
int bucket_count;
vector<list<string>> table(bucket_count);
//bool isEmpty(list<string> &cell) const;
int hashFunction(const string& s);
void insertItem(string value);
void removeItem(string value);
bool searchTable(string s);
void printTable();
void processQueries();
void processQuery(const Query& query);
};
I tried making a constructor which worked for me, but I am not sure why it worked.
Here is my code:
HashTable::HashTable(int bc)
: bucket_count(bc)
, table(bucket_count)
{}
In this, the bucket_count is initialized to bc in this constructor which is agreeable. But by that logic table should be initialized to bc. But that is not what happened. Instead the size of table vector got initialized (which is what I wanted).
If anyone could explain, why the constructor initialization worked this way it would be of great help.
The easiest solution would be
vector<list<string>> table{(size_t)bucket_count};
This depends largely on how, where and when you set the actual value of bucket_count. For example, you could set the size of the table vector in the initializer list of your class constructor. The following code lets you do this by setting the size in the constructor call, either by passing a size explicitly when you construct a class object, or by using a default value (42 in the code I've shown):
class HashTable {
public:
int bucket_count;
vector<list<string>> table;
HashTable(int bc = 42) : bucket_count(bc), table(bucket_count) { }
//...
Alternatively, if bucket_size is to remain constant and universal, you could make it a static constexpr member:
class HashTable {
public:
static constexpr auto bucket_count = 42;
vector<list<string>> table;
HashTable() : table(bucket_count) { }
//...

Set const int member variable outside the class (C++)

Let's say this is in Foo.h:
class Foo {
private:
const int MAXIMUM;
}
How do I initialize MAXIMUM to a certain value (100 in this case) in the Foo.cpp file? I tried
Foo::Foo() {
MAXIMUM = 100;
}
and got the error "expression must be a modifiable lvalue". Then I tried
const int Foo::MAXIMUM = 100;
and got the error "a nonstatic data member may not be defined outside its class". And that basically answers my question as "it's just not possible" but that just means my university messed up on the header file. So, is this possible or not?
Note: This is a university assignment, so I can't change the header file. I assume the logical solution would be to set MAXIMUM to 100 in the header file.
You can initialise const variables in two ways
In line initialisation
class Foo {
private:
const int MAXIMUM = 100;
};
Using initialisation list
class Foo {
Foo()
: MAXIMUM(100) {
}
Foo(const int MAXIMUM)
: MAXIMUM(MAXIMUM) {
}
private:
const int MAXIMUM;
}
In the below statenter code hereement
Foo::Foo() {
MAXIMUM = 100;
}
MAXIMUM is already created and you are trying to modify its value, which is not allowed for const variables.
In the below statement
const int Foo::MAXIMUM = 100;
MAXIMUM is not a static variable, so it will be bind with an object. You cannot access MAXIMUM using class name.
You want an initializer list:
Foo::Foo() : MAXIMUM(100)
{
}
"Const" and "Reference" variables are need to be initialized before class object is created. In your case,
Foo::Foo() { // **End of this line, object is getting created.**
MAXIMUM = 100; // *This line, gets Error: "expression must be a modifiable lvalue"*
}
to avoid this, you must use "Initialization list" where the value is assigned to variable before class constructor creates object.
Fix:
Foo::Foo():MAXIMUM(100) { // const variable is initialized
MAXIMUM = 200;
}

Have const variables in an object which is used in a vector container

So I am trying to make snake clone.
I have made a BodyPiece class which has certain variables I would like to be const, as they should not change. This was not a problem when I simply created an instance of Bodypiece to test out. However I want to be able to add pieces as the snake grows so I made a vector body variable. As you can see from the code below:
In BodyPiece.h:
#pragma once
#include "D3DGraphics.h"
#include "Keyboard.h"
#include "Direction.h"
class BodyPiece
{
public:
BodyPiece(int xPos, int yPos, Direction* dir);
~BodyPiece();
void Draw(D3DGraphics& gfx);
void UpdateDirection(KeyboardClient& kbd);
void Move();
private:
Direction* dir;
int xPos;
int yPos;
int width = 5;
int height = 5;
int vx = 5;
int vy = 5;
};
In Game.h file
BodyPiece vector body declared:
std::vector<BodyPiece> body;
In Game.cpp file
vector initialised in initialiser list.
body({ {400, 300, &d } })
If I make any variables in BodyPiece const, it will generate an error:
error C2582 'operator=' function is unavailable in class BodyPiece.
My questions here are:
What causes that? I have looked online and have a little bit of an idea but it really is only a little bit.
How can I have const variables, use a vector container(or another type of container if that will help, does not have to be vector) and keep the compiler happy? Or should I just completely change my approach?
Thank you in advance.
The problem is that if you don't have an assignment operator, then the compiler will generate one for you, that does simple shallow copying of the members. However, if you have actual const member variables (and not only default-initialized like yours) then those can't be copied and the compiler can't create an assignment operator.
The simple solution is to make the constants actual constants and also static so they are members of the class and not part of a single object:
class BodyPiece
{
...
static int const width = 5;
static int const height = 5;
};
The only drawback with this is that you need to actually define these member variables, in a single source file:
int const BodyPiece::width;
int const BodyPiece::height;
The other solution is to explicitly create an assignment operator that copies the data needed:
class BodyPiece
{
public:
...
BodyPiece& operator=(BodyPiece const& other)
{
// Copy data from other to this
xPos = other.xPos;
...
return *this;
}
...
};

Correctly initializing static array of objects without encountering initialization order fiasco using object references

I'm trying to implement a lightweight map by simply using an array of elements whose members are a key and a value. The map contents are known at compile-time so I think of using a fixed-size array as follows:
#include "stdafx.h"
#include <string>
// class Item is declared in file1.h. Definition could be in file1.cpp.
class Item
{
public:
Item(const std::string name) : m_name(name) {}
const std::string GetName() const { return m_name; }
private:
const std::string m_name;
};
// The static consts are declared in file2.h which includes file1.h.
static const Item ITEM1 = std::string("Item1");
static const Item ITEM2 = std::string("Item2");
static const Item ITEM3 = std::string("Item3");
static const Item ITEM4 = std::string("Item4");
// ItemMapEntry and ItemMapUser is defined in file3.h...
struct ItemMapEntry
{
const Item& key;
const Item& value;
};
class ItemMapUser
{
public:
void Run();
private:
static const ItemMapEntry map[];
};
// and declared in file3.cpp which includes file2.h.
const ItemMapEntry ItemMapUser::map[] =
{
{ ITEM1, ITEM2 },
{ ITEM3, ITEM4 }
};
void ItemMapUser::Run()
{
for (int i = 0; i < (sizeof(map) / sizeof(map[0])); i++)
{
printf("%s %s\n", map[i].key.GetName().c_str(), map[i].value.GetName().c_str());
}
}
// main.cpp includes file3.h.
int main()
{
ItemMapUser itemMapUser;
itemMapUser.Run();
}
Now to my question: The code snippet works as intended but I somehow have the feeling that I'm relying on the initialization order to have the ITEM1 to ITEM4 having their content initialized before using them in the ItemMapUser::map. I searched through the many questions referring to this topic (especially those with the static-order-fiasco tag) but couldn't find any one related to the use of arrays.
May I encounter the initialization order fiasco?
If no, what prevents it from happening here?
Does it matter that I'm using an array? How would it look like if I tried to initialize a simple variable using const Item anotherItem = ITEM1; for example?
Do you use ItemMapUser::map in code which can be called from
the constructor of a static object? There's no problem
initializing the references with unconstructed objects, but
there will be if you use them before the object is constructed.
Re your questions:
Not unless you actually use the objects the references
designate in the constructor of a static object.
Basically, the fact that these are references, and you can
safely initialize a referene with an unconstructed object.
(There are certain restrictions when inheritance is involved,
but they don't seem to be relevant here.)
It has nothing to do with whether you're initializing an
object or an array. If you're initialization an object
(member of an array or not) rather than a reference, and calling
the copy constructor, the object being copied had better be
constructed. Which you can only guarantee if it is defined in
the same translation unit.
I would say yes you may encounter the static initialization order fiasco.
The reason you have not encountered it yet is that the application has not yet got complicated enough to create a circular static initialization.
I don't think using an array makes any difference.
At any rate it isn't a risk worth taking. I would start with the following pattern and evolve it as required, i.e. creating a static class or whatever best suits your purpose.
#include <iostream>
#include <string>
#include <map>
using namespace std;
// Define safely in any module and use safely from any module.
// With C++11 use of an initializer list could eliminate the init statement.
// If you want to define the constants separately from the map use of constexpr
// should preclude any initialization order issues.
static const map<string, string>& Map()
{
static map<string, string> map;
static bool init = false;
if(!init)
{
map["Item1"] = "Item2";
map["Item3"] = "Item4";
init = true;
}
return map;
}
int main()
{
cout << "Hello world!";
}
Maybe the question was simplified in the course of asking, but there's an awful lot of thrashing going on here for something that's basically much simpler.
struct entry {
const char *key;
const char *value;
};
entry data_map[] = {
"Item1", "Item2",
"Item3", "Item4",
0, 0
};
for (entry *current = data_map; current->key != 0; ++current)
printf("%s %s\n", current->key, current->value);

how to initialize a static struct in c++?

I have managed to initialize correct any variable of basic type(i.e. int, char, float etc) but when declaring a little complex variable all i can see is errors.
In the header file timer.h i declare
class AndroidTimerConcept {
...
private:
//struct that holds the necessary info for every event
struct Resources{
timer_delegate_t membFunct;
void *data;
int size;
millis_t time;
};
//declaring an array of 10 Resources structs
static struct Resources ResData;
static int best;
...
}
inside the timer.cpp file
#include <iostream>
#include "timer.h"
using namespace std;
int AndroidTimerModel::best=1000;
struct Resources AndroidTimerModel::ResData.size; //line 17!!
//constructor that initializes all the necessary variables
AndroidTimerModel::AndroidTimerModel()
{
signal(SIGALRM,signalHandler);
for(int i=0; i<MAX_EVENTS; i++)
{
//ResData.data=NULL;
ResData.size=-1;
//ResData.time=-1;
}
best=1000;
}
when compiling the .cpp file i get the error:
timer.cpp:7: error: expected initializer before ‘.’ token
Any suggestions would be really helpful.
btw i use g++
You can use a struct initializer in C++, but only in the pre-C99 style (i.e, you cannot use designated initializers). Designated intializers, which allow you to specify the members to be initialized by name, rather than relying on declaration order, were introduced in C99, but aren't part of any C++ standard at the moment (belying the common assumption that C++ is a superset of C).
If you are willing to write non-portable C++ code that specifically targets g++, you can always use the GCC-specific extension which has the same functionality as designated constructors. The syntax is like this:
struct value_t my_val = { member_a: 1, member_b: 1.2f };
This reference provides a pretty good overview of both types of initialization in the C context.
Here's an excerpt that shows both the earlier (without designators) and C99 styles:
When initializing a struct, the first initializer in the list
initializes the first declared member (unless a designator is
specified) (since C99), and all subsequent initializers without
designators (since C99) initialize the struct members declared after
the one initialized by the previous expression.
struct point {double x,y,z;} p = {1.2, 1.3}; // p.x=1.2, p.y=1.3, p.z=0.0
div_t answer = {.quot = 2, .rem = -1 }; // order of elements in div_t may vary
In some cases you may need to write some code to initialize a structure, and in this case you can use the result of a function, like:
struct Resources AndroidTimerModel::ResData = function_that_acts_like_a_constructor();
You don't separately define individual instance members within a static member.
This should be enough:
AndroidTimerModel::Resources AndroidTimerModel::ResData;
You need to declare and define a constructor for struct Resources.
eg
struct Resources{
timer_delegate_t membFunct;
void *data;
int size;
millis_t time;
Resources():membFunct(0), data(0), size(0), time(0) {}
....
};
You need to initialise the whole struct variable, something like this:
AndroidTimerConcept::Resources AndroidTimerModel::ResData = { NULL, NULL, 0, 0 };
Is it AndroidTimerModel or AndroidTimerConcept, you can't use different names and expect the compiler to think they're the same thing.
You need to scope the name Resources, it's not in global scope, it's in the scope of the AndroidTimerModel class:
AndroidTimerModel::Resources AndroidTimerModel::ResData;
I suggest you give Resources a constructor:
struct Resources{
Resources(timer_delegate_t aMembFunct, void* aData, int aSize, millis_t aTime )
: membFunc(aMembFunct)
, data(aData)
, size(aSize)
, time(aTime)
{}
timer_delegate_t membFunct;
void *data;
int size;
millis_t time;
};
And you can then define Res in your .cpp as:
AndroidTimerModel::Resources AndroidTimerModel::ResData(/* params here */);
Why is your struct part of a class? I would make it global outside of the class.
memset(&structname, 0, sizeof(structname)); will initialize your structure to 0.