Initializing struct array with constructor parameters - c++

How can I initialize struct array with parameters in constructor?
Now I have this code:
struct roundMatrix {
private:
int **matrix;
public:
roundMatrix(int teamsNumber) {
matrix = new int*[teamsNumber];
for(int i=0;i<teamsNumber;i++) {
matrix[i] = new int[teamsNumber];
}
}
int addPartners(int first, int second) {
if(matrix[first][second] == -1 && matrix[second][first] == -1) {
matrix[first][second] = 0;
matrix[second][first] = 0;
}
else {
return -1;
}
return 0;
}
};
...
Then I need to inintialize array of roundMatrix with parameter:
roundMatrix rounds[roundsNumber](teamsNumber);
And I got an error:
variable-sized object 'rounds' may not be initialized
One more question. How can I initialize vector with struct and constructor paramaters?

You cannot initialize array in that way. It should be written as:
roundMatrix rounds[roundsNumber] = {teamsNumber, teamsNuber, ...);
Alternatively you need to implement a default constructor for roundMatrix class that will automatically initialize the items in your array.

At first your struct is class. struct should be used in C++ without methods, inheritance, encapsulation and other class's stuff as same as in standart C code.
Next, class names should be in upper camel case: first character of the name should be in uppercase and each new word in the name should begin from uppercase character. By the way your corporate code conventions may override this default convention which uses almost everywhere in C++ code.
And last: in case you have an array of objects of this class you can't call constructor for each object of this class during initialization. You can do something like that:
roundMatrix *rounds = new roundMatrix[roundsNumber];
for(i = 0; i < roundsNumber; i++)
rounds[i] = roundMatrix(teamsNumber);

Related

c++ error: array initializer must be an initializer list

I have really been struggling with a piece of code for a couple days. The error message i receive when i run my code is:
error: array initializer must be an initializer list
accountStore (int size = 0) : accts(size) { }
There seem to be others with similar problems here but unfortunately I am unable to apply their solutions (either don't work or not applicable).
What I am simply attempting to do is create a container class (array, can't use vectors) of a class 'prepaidAccount' but I am just unable to get the constructor portion of the container class 'storeAccount' to work. See code snippet below:
class prepaidAccount{
public:
//prepaidAccount ();
prepaidAccount(string newPhoneNum, float newAvailBal) : phoneNumber(newPhoneNum), availableBalance (newAvailBal){} //constructor
double addBalance(double howMuch) {
availableBalance = howMuch + availableBalance;
return availableBalance;
}
double payForCall(int callDuration, double tariff) {
callDuration = callDuration/60; //convert to minutes
double costOfCall = callDuration * tariff;
if (costOfCall > availableBalance) {
return -1;
}
else {
availableBalance = availableBalance - costOfCall;
return costOfCall;
}
}
void setAvailBal(int newAvailBal) {availableBalance = newAvailBal;}
float getAvailBal() {return availableBalance;}
void setPhoneNum(string newPhoneNum) {phoneNumber = newPhoneNum;}
string getPhoneNum() const {return phoneNumber;}
private:
string phoneNumber;
float availableBalance;
};
class accountStore { //made to store 100 prepaid accounts
public:
accountStore (int size = 0) : accts(size) { }
....
private:
prepaidAccount accts[100];
}
In main I simply call accountStore Account;
Any help is absolutely welcome. I very recently started learning c++ and about classes and constructors so please bear with me.
Thanks
You can't initialize an array with int like accountStore (int size = 0) : accts(size) {}.
prepaidAccount doesn't have a default constructor, you have to write member initialization list like,
accountStore (int size = 0) : accts{prepaidAccount(...), prepaidAccount(...), ...} { }
The array has 100 elements, it's not a practical solution here.
As a suggestion, think about std::vector, which has a constructor constructing with the spicified count of elements with specified value. Such as,
class accountStore {
public:
accountStore (int size = 0) : accts(size, prepaidAccount(...)) { }
....
private:
std::vector<prepaidAccount> accts;
};
Given that you have specified that you do not want to use a container such as std::vector but would like to specify the size at runtime, your only option would be to manually implement dynamic allocation yourself. Also given that you are wanting create 100 objects at a time, I would suggest making a function that can construct a temporary object according to your needs and then use this to initialise your dynamically allocated array. Consider the below code as a good starting point. (WARNING untested code.)
class prepaidAccount {
public:
// Constructor
prepaidAccount(string newPhoneNum, float newAvailBal)
: phoneNumber(newPhoneNum), availableBalance(newAvailBal) {}
// Default Constructor needed for dynamic allocation.
prepaidAccount() {}
/* your code*/
};
// Used to construct a tempoary prepaid account for copying to the array.
// Could use whatever constructor you see fit.
prepaidAccount MakePrepaidAccount(/*some parameters*/) {
/* Some code to generate account */
return some_var;
}
class accountStore {
public:
// Explicit constructor to avoid implicit type-casts.
explicit accountStore(const int &size = 0)
: accts(new prepaidAccount[size]) {
for (int i = 0; i < size; i++) {
// Will call defualt assignment function.
prepaidAccount[i] = MakePrepaidAccount(/*some parameters*/);
}
}
// Destructor
~accountStore() {
// Cleans up dynamically allocated memory.
delete[] prepaidAccount;
}
prepaidAccount *accts;
};
Edit: Amongst the c++ community it is often questionable when choosing to use dynamic allocation when there is such an excellent and comprehensive library of smart pointers. For example an std::vector would be perfect in this situation.

How to msgpack a user-defined C++ class with POD-arrays?

How it is possible to provide all three functions: msgpack_pack, msgpack_unpack and msgpack_object (also, what are meanings of them, exactly?) for a user-defined C++ class (in the same way MSGPACK_DEFINE does it for non-array POD/UD types) containing Plain Old Data arrays (such as dobule[] or char[]), so my class will play nicely with higher-level classes, containg this class in map or a vector?
Is there any examples of implementing them for your own class or at least msgpack C++ api documentation?
The only link to possible api reference i've found was http://redmine.msgpack.org/projects/msgpack/wiki ; but it is dead now.
Say, i have a struct like
struct entity {
const char name[256];
double mat[16];
};
What would be a msgpack_* member functions for it?
Thanks to guy who -1'd my question, i felt grievance and explored the actual undocumented codebase of msgpack. Here is the example of mentioned earlier functions with sort of explanation, in amount of my (vastly incomplete due to missing docs) understanding:
struct entity {
char name[256];
double mat[16];
// this function is appears to be a mere serializer
template <typename Packer>
void msgpack_pack(Packer& pk) const {
// make array of two elements, by the number of class fields
pk.pack_array(2);
// pack the first field, strightforward
pk.pack_raw(sizeof(name));
pk.pack_raw_body(name, sizeof(name));
// since it is array of doubles, we can't use direct conversion or copying
// memory because it would be a machine-dependent representation of floats
// instead, we converting this POD array to some msgpack array, like this:
pk.pack_array(16);
for (int i = 0; i < 16; i++) {
pk.pack_double(mat[i]);
}
}
// this function is looks like de-serializer, taking an msgpack object
// and extracting data from it to the current class fields
void msgpack_unpack(msgpack::object o) {
// check if received structure is an array
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
const size_t size = o.via.array.size;
// sanity check
if(size <= 0) return;
// extract value of first array entry to a class field
memcpy(name, o.via.array.ptr[0].via.raw.ptr, o.via.array.ptr[0].via.raw.size);
// sanity check
if(size <= 1) return;
// extract value of second array entry which is array itself:
for (int i = 0; i < 16 ; i++) {
mat[i] = o.via.array.ptr[1].via.array.ptr[i].via.dec;
}
}
// destination of this function is unknown - i've never ran into scenary
// what it was called. some explaination/documentation needed.
template <typename MSGPACK_OBJECT>
void msgpack_object(MSGPACK_OBJECT* o, msgpack::zone* z) const {
}
};

C++ how to display multidimentional array in OO design

Hi I'm writing a simple version of Pacman with OO design in C++. I have problem displaying the content of a 2D array. The array constains a bunch of symbols, which represent the wall of the map/maze. Here is the sample code that I wrote:
Game.h
class Game
{
private:
char map;
public:
Game();
void displayMap();
};
Game.cpp
char map[10][20] = {...};
void Game::displayMap()
{
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 20; j++)
{
cout << map[i][j] << " ";
}
cout << endl;
}
}
The compiler will pop out an error at [i] saying "expression must have pointer-to-object type".
But if I define the size of the array in the header file and assign its value when defining the constructor
Game.h
class Game
{
private:
char map[10][20];
};
Game.cpp
Game::Game()
{
char map[10][20] = {...};
}
It will compile but when I try to display the content of the array (using the same code of displayMap()), I found out it's filled with junk. I think it's because that assignment is not an assignment. It's actually an initialization of another array on the stack, so that array is destroyed after the constructor finishes, and the displayMap() at that time display the original unassigned array.
I could be wrong, so feel free to correct me. I need a recommendation on how should I structure my game to avoid this problem
Game::Game() {
char map[10][20] = {...};
}
Here you redeclare a local variable with the same name of the instance variable, hence you hide the outer one. In addition you are trying to assign to an array which has been declared before, that's not possible in C++. You can just initialise an array when you declare it, not afterwards.
You can do this (if you have C++11 support):
class Game {
char map[W][H] = { ... };
}
or you can do this:
class Game {
char map[W][H];
Game() {
char tmp[W][H] = { ... };
memcpy(map, tmp, sizeof(char)*W*H);
}
}
Even better, you can use std::copy. Or even even better just use an std::array and forget normal arrays.
I commented your question, but I think it would be good to make it an answer, so here it is.
The second option should work fine.
Garbage values are normal in C/C++.
What you have to do is to initialize your values inside your constructor ( Game::Game() ). Constructors are meant to be used in these cases.
The behavior of C/C++ is to not assign a default value, it just "takes what's in place in RAM". Other languages do initialize the RAM cells though. It all depends of what programming language you are using.
Including this code inside your constructor (before accessing map[][] for another thing) should work:
for (int ix = 0; ix < 10; ix++)
for (int jx = 0; jx < 20; jx++)
map[ix][jx] = "x"; // x will be your default value

How can I access a class's member function via an array of pointers?

I have a pretty standard class with some public member functions and private variables.
My problem originally stems from not being able to dynamically name object instances of my class so I created an array of pointers of the class type:
static CShape* shapeDB[dbSize];
I have some prompts to get info for the fields to be passed to the constructor (this seems to work):
shapeDB[CShape::openSlot] = new CShape(iParam1,sParam1,sParam2);
openSlot increments properly so if I were to create another CShape object, it would have the next pointer pointing to it. This next bit of code doesn't work and crashes consistently:
cout << shapeDB[2]->getName() << " has a surface area of: " << shapeDB[2]->getSA() << shapeDB[2]->getUnits() << endl;
The array of pointers is declared globally outside of main and the get() functions are public within the class returning strings or integers. I'm not sure what I'm doing wrong but something relating to the pointer set up I'm sure. I'm writing this code to try and learn more about classes/pointers and have gotten seriously stumped as I can't find anyone else trying to do this.
I'm also curious as to what the CShape new instances get named..? if there is any other way to dynamically create object instances and track the names so as to be able to access them for member functions, I'm all ears.
I've tried all sorts of permutations of pointer referencing/de-referencing but most are unable to compile. I can post larger chunks or all of the code if anyone thinks that will help.
class CShape {
int dim[maxFaces];
int faces;
string units;
string type;
string name;
bool initialized;
int slot;
public:
static int openSlot;
CShape();
CShape(int, string, string); // faces, units, name
~CShape();
void initialize(void);
// external assist functions
int getA(void) {
return 0;
}
int getSA(void) {
int tempSA = 0;
// initialize if not
if(initialized == false) {
initialize();
}
// if initialized, calculate SA
if(initialized == true) {
for(int i = 0; i < faces; i++)
{
tempSA += dim[i];
}
return(tempSA);
}
return 0;
}
string getUnits(void) {
return(units);
}
string getName(void) {
return(name);
}
// friend functions
friend int printDetails(string);
};
// constructor with values
CShape::CShape(int f, string u, string n) {
initialized = false;
faces = f;
units = u;
name = n;
slot = openSlot;
openSlot++;
}
My guess is you use the CShape constructor to increment CShape::openSlot?
You're probably changing the value before it's read, thus the pointer is stored in a different location.
Try replacing openSlot with a fixed value to rule out this CShape::option.
-- code was added --
I'm pretty sure this is the problem, the constructor is executed before the asignment, which means the lhs. will be evaluated after CShape::openSlot is incremented.

Problem passing a list of objects to another class, C++

Below I have written a sample program that I have written to learn about passing a list of objects to another class. I talk about the problems I am having below.
#include <iostream>
#include <vector>
using namespace std;
class Integer_Class
{
int var;
public:
Integer_Class(const int& varin) : var(varin) {}
int get_var() { return var; }
};
class Contains_List
{
typedef Integer_Class* Integer_Class_Star;
Integer_Class_Star list;
public:
Contains_List(const Integer_Class_Star& listin) : list(listin) {}
Integer_Class* get_list() { return list; }
};
int main (int argc, char * const argv[])
{
// Create a vector to contain a list of integers.
vector<Integer_Class> list;
for(int i = 0; i < 10; i++)
{
Integer_Class temp_int(i);
list.push_back(temp_int);
}
This is where the errors start occuring. Could someone please look at the second class definition and the code below and shed some light on what I'm doing wrong. Thank you so much, as always!
// Import this list as an object into another object.
Contains_List final(list);
// Output the elements of the list by accessing it through the secondary object.
for(int i = 0; i < 10; i++)
{
cout << final.get_list()[i].get_var();
}
return 0;
}
You don't mention what sort of errors you are getting, but one very obvious problem with your code is that the constructor for Contains_List expects a pointer to Integer_Class while the parameter you are sending it (list) is of type vector<Integer_Class>.
A vector is not the same as an array, so you cannot pass it as pointer to the type it contains. Either change your constructor to accept a vector or pointer/reference to vector, or change the code that is causing you problems so that it sends it a pointer to an array.
The 'Contains_List' constructor takes in an 'Integer_Class*'
You declare 'list' to be of type 'vector', yet you pass it to the the 'Contians_List' constructor. You should change the 'Contains_List' class so that it holds a vector instead of an Integer_List array. The two are not interchangeable.
You could also change the vector to be an array of Integer_List's instead, if you so wished.