How to create dynamic objects in member function? [closed] - c++

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
In a member function of Class Championship, I try to create dynamic objects and call the member function of Class Game, but I got the error message as error: expected primary-expression before '[' token. How to correct it?
class Championship
{
public:
Championship(string,int);
void CreateGame();
void display();
private:
int gamenum;
};
class Game
{
public:
friend class Championship;
void Getteam();
};
void Championship::CreateGame()
{
Game *game = new Game[gamenum];
for (int i = 0; i < gamenum; i++)
Game[i].Getteam();
}

The exact problem you are facing in your code is in this small bit
Game *game = new Game[gamenum];
for (int i = 0; i < gamenum; i++)
Game[i].Getteam();
The main issue here is that you have declare an array of type Game and call it game but then you try to access using Game which is the type, so simply swapping that back to game would fix that issue.
However, there is no need for using raw pointers in this way. std::vector is superior in so many ways here. It allows you to dynamically add more and more objects into the container in a safe way. I was about to show how std::vector could be used in your Championship::CreateGame() function... but I can't really work out what it is trying to do...
I also don't see why you have the friend line in your game class... that is used to give another class 'full' access to your class, ie the Championship class is given access to private members of Game.

Edit: While this answer doesn't directly solve the problem, it does provide a useful alternative syntax for allocating arrays of User-Defined Objects.
This can probably be solved not-so-elegantly using the classic C-style double-pointer array (i.e. argv from int main(int argc, char** argv). Such code would first allocate the space for the array, and then allocate the space for each individual object using a loop with an index.
#include <iostream>
class Foo
{
public:
//Constructor to ensure each object is unique with an int + loop
Foo(int k)
: i(k)
{}
int i;
int operator() () {return i;}
};
int main ()
{
//Arbitrary number for allocation; get this somehow
int i = 5;
//Although it can be unsafe, allocate an array of pointers with a pointer to pointer
Foo** array = new Foo*[i];
for (int j = 0; j < i; ++j)
{
array[j] = new Foo(j);
//Here, I use operator() to test that each object is unique.
std::cout << (*array[j])() << std::endl;
}
//Using Coliru, the program will work and print out this
std::cout << "this worked!\n";
return 0;
}
Coliru: http://coliru.stacked-crooked.com/a/84f7641e5c4fa2f3

Related

Initializing an object as in a vector class [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 11 months ago.
Improve this question
So, I know a vector object can be declared and initialized like this:
// Nothing new here. I know <int> is a template
// and how to implement it:
vector <int> vect{ 10, 20, 30 };
I assume that the vector object has inside an array of values, and the functions of that class (like push_back() for example) manage it. I would like and have been trying to implement something like that in a class of my own, without success. Would be interesting being able to understand how it's done! Did many "experiments" but none worked.
// Random named class:
class A_Class
{
private:
// A pointer for the type I want:
int *A_pointer_To_int;
public:
// Trying to accept the input values between
// brackets and putting them inside a temp array:
A_Class(int Input_Array[]) {}
};
int main()
{
// trying to create the object like in the vector class.
// Returns error "No instance of constructor matches the argument list":
A_Class My_Object{1,2,3}
return 0;
}
In a function parameter, int Input_Array[] is just syntax sugar for a decayed pointer int* Input_Array, which does not provide any information about any array that may be passed in to it.
For what you are attempting, you need to accept a std::initializer_list instead, eg:
#include <initializer_list>
#include <algorithm>
// Random named class:
class A_Class
{
private:
// A pointer for the type I want:
int *A_pointer_To_int;
// the number of values in the array:
size_t size;
public:
A_Class(std::initializer_list<int> Input_Values) {
size = Input_Values.size();
A_pointer_To_int = new int[size];
std::copy(Input_Values.begin(), Input_Values.end(), A_pointer_To_int);
}
~A_Class() {
delete[] A_pointer_To_int;
}
};
int main()
{
A_Class My_Object{1,2,3}; // works now
return 0;
}
Online Demo

Trying to delete a dynamically allocated object causes a run-time crash [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm working on optimizing my current CLI project. When looking through the code and debugging I've noticed that I haven't released some dynamically allocated memory in a class. Here's how my code looks:
"Coordinates.h"
#pragma once
#include <Windows.h>
#define LENGTH 40
#define WIDTH 15
struct Coordinate
{
int x = 1;
int y = 1;
};
"Laser.h"
#pragma once
#include "Coordinates.h"
class Laser
{
private:
Coordinate* initCoord;
char icon;
public:
Laser(int x, int y);
char getIcon() const;
Coordinate* getCoord();
void move();
};
"Laser.cpp"
#include "Laser.h"
Laser::Laser(int x, int y)
{
initCoord = new Coordinate;
initCoord->x = x;
initCoord->y = y;
icon = '~';
}
char Laser::getIcon() const { return icon; }
Coordinate* Laser::getCoord() { return initCoord; }
void Laser::move()
{
++initCoord->x;
}
I've tried adding a destructor (declaring it in the header file first of course) which clears up the memory allocated for initCoord which looked something like this:
Laser::~Laser()
{
if(initCoord != nullpr) delete initCoord;
}
After adding that it caused a run-time error. "ProgramName.exe has stopped working..." Objects of this class are stored in a simple vector which gets cleared at one time of the program. The problem is that the crash happens before it even reaches the lasers.clear() line. I honestly have no idea why this crash is happening and would appreciate some help. Thank you! :)
If you consider this code
int main() {
Laser one(0,0);
{
Laser two = one;
cout << two.getCoord()->x << endl;
}
return 0;
}
What do you expect to be written?
"0"
which mean that the coordinate points to the same structure as one which again means that when the first } happens and two gets destroyed one doesn't have a valid coordinate any more.
When you have a pointer member you need to either disable copying/assigning or implement them.
In this case you could also have been rescued if you had used a std::unique_ptr instead of the raw pointer (which also saves you the delete).

Trouble implementing min Heaps in C++

I'm trying to implement a minheap in C++. However the following code keeps eliciting errors such as :
heap.cpp:24:4: error: cannot convert 'complex int' to 'int' in assignment
l=2i;
^
heap.cpp:25:4: error: cannot convert 'complex int' to 'int' in assignment
r=2i+1;
^
heap.cpp: In member function 'int Heap::main()':
heap.cpp:47:16: error: no matching function for call to 'Heap::heapify(int [11], int&)'
heapify(a,i);
^
heap.cpp:47:16: note: candidate is:
heap.cpp:21:5: note: int Heap::heapify(int)
int heapify(int i) //i is the parent index, a[] is the heap array
^
heap.cpp:21:5: note: candidate expects 1 argument, 2 provided
make: * [heap] Error 1
#include <iostream>
using namespace std;
#define HEAPSIZE 10
class Heap
{
int a[HEAPSIZE+1];
Heap()
{
for (j=1;j<(HEAPISZE+1);j++)
{
cin>>a[j];
cout<<"\n";
}
}
int heapify(int i) //i is the parent index, a[] is the heap array
{
int l,r,smallest,temp;
l=2i;
r=2i+1;
if (l<11 && a[l]<a[i])
smallest=l;
else
smallest=i;
if (r<11 && a[r]<a[smallest])
smallest=r;
if (smallest != i)
{
temp = a[smallest];
a[smallest] = a[i];
a[i]=temp;
heapify(smallest);
}
}
int main()
{
int i;
for (i=1;i<=HEAPSIZE;i++)
{
heapify(a,i);
}
}
}
Ultimately, the problem with this code is that it was written by someone who skipped chapters 1, 2 and 3 of "C++ for Beginners". Lets start with some basics.
#include <iostream>
using namespace std;
#define HEAPSIZE 10
Here, we have included the C++ header for I/O (input output). A fine start. Then, we have issued a directive that says "Put everything that is in namespace std into the global namespace". This saves you some typing, but means that all of the thousands of things that were carefully compartmentalized into std:: can now conflict with names you want to use in your code. This is A Bad Thing(TM). Try to avoid doing it.
Then we went ahead and used a C-ism, a #define. There are times when you'll still need to do this in C++, but it's better to avoid it. We'll come back to this.
The next problem, at least in the code you posted, is a misunderstanding of the C++ class.
The 'C' language that C++ is based on has the concept of a struct for describing a collection of data items.
struct
{
int id;
char name[64];
double wage;
};
It's important to notice the syntax - the trailing ';'. This is because you can describe a struct and declare variables of it's type at the same time.
struct { int id; char name[64]; } earner, manager, ceo;
This declares a struct, which has no type name, and variables earner, manager and ceo of that type. The semicolon tells the compiler when we're done with this statement. Learning when you need a semicolon after a '}' takes a little while; usually you don't, but in struct/class definition you do.
C++ added lots of things to C, but one common misunderstanding is that struct and class are somehow radically different.
C++ originally extended the struct concept by allowing you to describe functions in the context of the struct and by allowing you to describe members/functions as private, protected or public, and allowing inheritance.
When you declare a struct, it defaults to public. A class is nothing more than a struct which starts out `private.
struct
{
int id;
char name[64];
double wage;
};
class
{
public:
int id;
char name[64];
double wage;
};
The resulting definitions are both identical.
Your code does not have an access specifier, so everything in your Heap class is private. The first and most problematic issue this causes is: Nobody can call ANY of your functions, because they are private, they can only be called from other class members. That includes the constructor.
class Foo { Foo () {} };
int main()
{
Foo f;
return 0;
}
The above code will fail to compile, because main is not a member of Foo and thus cannot call anything private.
This brings us to another problem. In your code, as posted, main is a member of Foo. The entry point of a C++ program is main, not Foo::main or std::main or Foo::bar::herp::main. Just, good old int main(int argc, const char* argv[]) or int main().
In C, with structs, because C doesn't have member functions, you would never be in a case where you were using struct-members directly without prefixing that with a pointer or member reference, e.g. foo.id or ptr->wage. In C++, in a member function, member variables can be referenced just like local function variables or parameters. This can lead to some confusion:
class Foo
{
int a, b;
public:
void Set(int a, int b)
{
a = a; // Erh,
b = b; // wat???
}
};
There are many ways to work around this, but one of the most common is to prefix member variables with m_.
Your code runs afoul of this, apparently the original in C passed the array to heapify, and the array was in a local variable a. When you made a into a member, leaving the variable name exactly the same allowed you not to miss the fact that you no-longer need to pass it to the object (and indeed, your heapify member function no-longer takes an array as a pointer, leading to one of your compile errors).
The next problem we encounter, not directly part of your problem yet, is your function Heap(). Firstly, it is private - you used class and haven't said public yet. But secondly, you have missed the significance of this function.
In C++ every struct/class has an implied function of the same name as the definition. For class Heap that would be Heap(). This is the 'default constructor'. This is the function that will be executed any time someone creates an instance of Heap without any parameters.
That means it's going to be invoked when the compiler creates a short-term temporary Heap, or when you create a vector of Heap()s and allocate a new temporary.
These functions have one purpose: To prepare the storage the object occupies for usage. You should try and avoid as much other work as possible until later. Using std::cin to populate members in a constructor is one of the most awful things you can do.
We now have a basis to begin to write the outer-shell of the code in a fashion that will work.
The last change is the replacement of "HEAPSIZE" with a class enum. This is part of encapsulation. You could leave HEAPSIZE as a #define but you should expose it within your class so that external code doesn't have to rely on it but can instead say things like Heap::Size or heapInstance.size() etc.
#include <iostream>
#include <cstdint> // for size_t etc
#include <array> // C++11 encapsulation for arrays.
struct Heap // Because we want to start 'public' not 'private'.
{
enum { Size = 10 };
private:
std::array<int, Size> m_array; // meaningful names ftw.
public:
Heap() // default constructor, do as little as possible.
: m_array() // says 'call m_array()s default ctor'
{}
// Function to load values from an istream into this heap.
void read(std::istream& in)
{
for (size_t i = 0; i < Size; ++i)
{
in >> m_array[i];
}
return in;
}
void write(std::ostream& out)
{
for (size_t i = 0; i < Size; ++i)
{
if (i > 0)
out << ','; // separator
out << m_array[i];
}
}
int heapify(size_t index)
{
// implement your code here.
}
}; // <-- important.
int main(int argc, const char* argv[])
{
Heap myHeap; // << constructed but not populated.
myHeap.load(std::cin); // read from cin
for (size_t i = 1; i < myHeap.Size; ++i)
{
myHeap.heapify(i);
}
myHead.write(std::cout);
return 0;
}
Lastly, we run into a simple, fundamental problem with your code. C++ does not have implicit multiplication. 2i is the number 2 with a suffix. It is not the same as 2 * i.
int l = 2 * i;
There is also a peculiarity with your code that suggests you are mixing between 0-based and 1-based implementation. Pick one and stick with it.
--- EDIT ---
Technically, this:
myHeap.load(std::cin); // read from cin
for (size_t i = 1; i < myHeap.Size; ++i)
{
myHeap.heapify(i);
}
is poor encapsulation. I wrote it this way to draw on the original code layout, but I want to point out that one reason for separating construction and initialization is that it allows initialization to be assured that everything is ready to go.
So, it would be more correct to move the heapify calls into the load function. After all, what better time to heapify than as we add new values, keeping the list in order the entire time.
for (size_t i = 0; i < Size; ++i)
{
in >> m_array[i];
heapify(i);
}
Now you've simplified your classes api, and users don't have to be aware of the internal machinery.
Heap myHeap;
myHeap.load(std::cin);
myHeap.write(std::cout);

Why can't my silly cardgame classes talk to each other? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I have tried to make some sort of card game here but the classes for the holder / cardpile don't give away right things to the reciver/player and I don't know how to sort this out.
Here is the program:
#include <iostream>
using namespace std;
class subclass // like a card
{
public:
subclass();
subclass(int x);
int nummer;
int getnummer();
};
subclass::subclass():nummer(0){}
subclass::subclass(int x):nummer(x){}
int subclass::getnummer()
{
return nummer;
}
holder class:
class holder // like a cardpile
{
public:
holder();
subclass cardpile[2];
subclass* pile; // a cardpile which has 2 cards, with nummber 1 and 2.
subclass* getsubclass(int i); // take first or second card.
};
holder::holder()
{
subclass first(1*3);
subclass second(2*3);
pile=cardpile;
pile=&first;
pile++;
pile=&second;
pile--;
}
subclass* holder::getsubclass(int i) //1 eller 2.
{
return pile+i;
}
reciver class/ the player
class reciver // like a player
{
public:
subclass part_of_holder;
reciver();
void getsubclass( subclass* in); // give this card to player from this pointer
void showinside(); // what card do player have
};
reciver::reciver():part_of_holder(){}
void reciver::getsubclass( subclass* in)
{
part_of_holder=*in;
}
void reciver::showinside() // what card do player have
{
cout<< part_of_holder.getnummer();
}
and the main
int main()
{
holder cardpile;
reciver player;
cout << "first card should be 1*3 and it is : " ;
player.getsubclass(cardpile.getsubclass(0));
player.showinside();
cout << endl <<"first card should be 2*3 and it is : " ;
player.getsubclass(cardpile.getsubclass(1));
player.showinside();
return 0;
}
In the end all I get is nonsence
holder::holder()
{
subclass first(1*3);
subclass second(2*3);
pile=cardpile;
pile=&first; // WRONG
pile++;
pile=&second; // WRONG
pile--;
}
The two lines above dont do what I suspect you think they do.
If you are trying to assign in the cardpile you would need something more like this:
cardpile[0] = first or *pile = first.
Sadly they wont work, since you dont have copy constructors. You also dont have any way to set a subclass's nummer field once constructed, so you are slightly doomed.
Add a setter function to the get instruction, and you could write this:
cardpile[0].setnummer(first.getnummer());
This is not going to work
holder::holder()
{
subclass first(1*3); // create temporary
subclass second(2*3); // create another temoporary
pile=cardpile; // assign member pointer to another member!!!
pile=&first; // assign member pointer to temporary
pile++;
pile=&second; // assign member pointer to temporary
pile--;
}
// member pointer pile points to object that no longer exists!!!
Basically once you create an instance of holder its internal pile pointer points to an object that no longer exists and that alone makes your class unstable because your getsubclass method returns an offset of this pointer - thus any attempt to dereference it will likely segfault.
In all honesty you would be better to start off again from scratch but a way of ensuring that you assign these temporaries to your member array would be
cardpile[0] = subclass(1*3);
cardpile[1] = subclass(2*3);
pile = cardpile;
however, the way this code is written is not a good design and I would advise starting from scratch when your grasp of C++ is better.

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