C++ Syntax errors - c++

I'm trying to make a kind of screen manager in C++ but I'm getting errors.
With my code below I receive
1>screenmanager.cpp(26): error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from 'virtualGameScreen' to 'virtualGameScreen *&&'
1> with
1> [
1> _Ty=virtualGameScreen *
1> ]
1> Reason: cannot convert from 'virtualGameScreen' to 'virtualGameScreen *'
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>
Errors occur with gameScreen.push_back(gameScreenToAdd);
I get access violation error when adding a reference operator with gameScreenToAdd.
ScreenManager.h
void AddScreen(virtualGameScreen);
void RemoveScreen(virtualGameScreen);
ScreenManager.cpp
std::vector<virtualGameScreen*> gameScreen;
void ScreenManager::Initialize(void)
{
MainMenu menu = MainMenu();
AddScreen(menu);
}
void ScreenManager::AddScreen(virtualGameScreen gameScreenToAdd)
{
gameScreenToAdd.LoadContent();
gameScreen.push_back(gameScreenToAdd);
}
So, I've hit a bit of a wall, any suggestions on how I might fix this?
edit game runs if I change gameScreen.push_back to gameScreen.push_back(new MainMenu()); buut that's not really how I want the function to work

So, the first thing the compiler did is tell you where the problem occurs:
1>screenmanager.cpp(26)
It also told you primarily what the problem is:
Reason: cannot convert from 'virtualGameScreen' to 'virtualGameScreen *'
So - something in your code is providing a "virtualGameScreen" object instance where it was expecting a pointer (denoted by the *). And it's on line 26. The other parts of the error indicate it's the call to push_back. Lets look at line 26:
gameScreen.push_back(gameScreenToAdd);
Yep - you're calling push_back, and you're passing it gameScreenToAdd, which is of type virtualGameScreen. The push_back call is from this vector:
std::vector<virtualGameScreen*> gameScreen;
Your vector expects pointers, so the push_back expects vectors.
HOWEVER: You can't just do this:
gameScreen.push_back(&gameScreenToAdd);
because gameScreenToAdd is a temporary function variable - when you call AddScreen, the original variable is copied into a new, temporary virtualGameScreen for the lifetime of the function call. That means when the program leaves AddScreen the screen whose address you pushed will no-longer exist (the memory is still there, but it has been released and the computer will now proceed to use it for other reasons).
What you'll need to do is change AddScreen to take a pointer.
void ScreenManager::AddScreen(virtualGameScreen* gameScreenToAdd)
{
gameScreenToAdd.LoadContent();
gameScreen.push_back(gameScreenToAdd);
}
Unfortunately, this leaves you open to yet another problem with your code.
void ScreenManager::Initialize(void)
{
MainMenu menu = MainMenu();
AddScreen(menu);
}
This function creates a temporary, local MainMenu object - with a lifetime of the duration of Initialize. Then it creates a second, temporary MainMenu and copies it to menu.
If you write
AddScreen(&menu);
it will work, but it will pass the address of a temporary instance to AddScreen.
As soon as program flow leaves the "Initialize()" function, your value goes away.
It looks like you may have some prior experience with something like Java or C# and are trying to apply previous knowledge to C++.
What you need is a member variable to store "Menu" for the life time of the instance of ScreenManager.
Option 1: Just use a class member variable.
class ScreenManager
{
MainMenu m_menu;
public:
ScreenManager()
: m_menu() // initialize menu while we are initializing.
{}
void Initialize()
{
AddScreen(&m_menu);
}
// ...
};
If you really want to use a pointer, you might do the following:
class ScreenManager
{
MainMenu* m_menu;
public:
ScreenManager()
: m_menu(nullptr) // make sure it's null as soon as the object is created
{}
void Initialize()
{
m_menu = new MainMenu();
AddScreen(m_menu);
}
// but now we have to make sure it is released when we go away
~ScreenManager()
{
if (m_menu)
{
delete m_menu;
m_menu = nullptr;
}
}
};
Option 3: use C++ containers to manage the lifetime of the pointer for you, either std::unique_ptr or std::shared_ptr
---- EDIT ----
Seeing the edit you made while I was writing this, it's a little clearer what you're trying to do. What you probably want is something more like this:
std::vector<std::unique_ptr<virtualGameScreen>> gameScreen;
Consider the following:
Live demo: http://ideone.com/7Th2Uk
#include <iostream>
#include <vector>
class Foo {
const char* m_name;
public:
Foo(const char* name) : m_name(name) { std::cout << "Foo " << m_name << '\n'; }
~Foo() { std::cout << "~Foo " << m_name << '\n'; }
};
int main() {
std::vector<Foo*> foos;
Foo foo("foo");
foos.push_back(new Foo("new"));
return 0;
}
Note that the second foo is never released.
Foo foo
Foo new
~Foo foo
std::unique_ptr is a pointer-container object which will delete the object when the object expires. This makes it suitable for use in a container like std::vector
#include <iostream>
#include <vector>
#include <memory> // for std::unique_ptr
class Foo {
const char* m_name;
public:
Foo(const char* name) : m_name(name) { std::cout << "Foo " << m_name << '\n'; }
~Foo() { std::cout << "~Foo " << m_name << '\n'; }
};
int main() {
std::vector<std::unique_ptr<Foo>> foos;
Foo foo("foo");
foos.emplace_back(new Foo("new"));
return 0;
}
Both objects get cleaned up:
Foo foo
Foo new
~Foo foo
~Foo new
Now you don't need your m_menu at all, you can simply call AddScreen with a 'new MainMenu()' and the pointer will be added to the vector such that when the vector goes out of scope, proper cleanup will happen.
Menu* menu = new MainMenu();
AddScreen(menu);
or
AddScreen(new MainMenu());
In theory what you should really do is ensure that the allocation goes straight into a unique_ptr object so that there's no window for it to get leaked, but teaching the use of std::unique_ptr is beyond the scope of this answer. http://msdn.microsoft.com/en-us/library/hh279676.aspx, http://www.drdobbs.com/cpp/c11-uniqueptr/240002708, etc.

In pre-C++11 code, you might have something like this:
std::vector<virtualGameScreen*> gameScreen;
void ScreenManager::Initialize(void)
{
AddScreen(new MainMenu);
}
void ScreenManager::AddScreen(virtualGameScreen *gameScreenToAdd)
{
gameScreenToAdd->LoadContent();
gameScreen.push_back(gameScreenToAdd);
}
but you would have to have some way to make sure the object got deleted.
With C++11, you would probably want to have the memory managed automatically:
std::vector<std::unique_ptr<virtualGameScreen>> gameScreen;
void ScreenManager::Initialize(void)
{
AddScreen(std::unique_ptr<MainMenu>(new MainMenu));
}
void ScreenManager::AddScreen(std::unique_ptr<virtualGameScreen> gameScreenToAdd)
{
gameScreenToAdd->LoadContent();
gameScreen.emplace_back(std::move(gameScreenToAdd));
}

That's because you did not provide a pointer to the vector (gameScreen), and another issue about the code is that: the paramater will generate a temp object, if just put the address of it the app maybe crash.

Related

EXC_BAD_ACCESS only when building object inside function

I'm working on a C++ project in XCode and I'm getting what appears to be some strange behavior (based on how I understand it). Here's my code:
#include <iostream>
#include <vector>
#include <string>
class beep {
public:
virtual void greet() {
std::cout << "bleep\n";
}
};
class boop : public beep {
public:
void greet() {
std::cout << "bloop\n";
}
};
class beep_master {
public:
std::vector<beep*> beeps;
void beep_everything() {
for (int i = 0; i < beeps.size(); i++) {
beeps[i]->greet();
}
}
};
beep_master factory() {
boop boop1;
boop boop2;
beep_master master;
master.beeps.push_back(&boop1);
master.beeps.push_back(&boop2);
return master;
}
int main(int argc, const char * argv[]) {
beep_master master = factory();
beep_master* ref = &master;
ref->beep_everything();
return 0;
}
I'm running this via XCode, and I'm getting an EXC_BAD_ACCESS in the for-loop in beep_master. Everywhere I've looked on the internet seems to indicate this is due to some memory management issues but I'm not really allocating anything dynamically.
I've noticed that if I move the contents of factory into main that I no longer get the error which leads me to believe it has something to do with boop1 and boop2 going out of scope and making the pointers invalid after the code exits that function.
Noodling on this, I'm beginning to think that this issue is unavoidable without the use of dynamic memory via the new operator and shared_ptr. Is this the right direction, or am I missing something in my setup here?
You are right. The factory function is storing pointers to local variables boop1 and boop2 which go away when the function returns, so you're left with pointers that point to invalid data.
You're pretty much going to have to dynamically allocate your objects to store the pointers in your vector.

Create struct object in a function and pass its pointer

I am trying to pass in a empty struct pointer into a function called "initialize" as an output parameter and then after the function finishes I could retrieve the object pointed by the struct pointer. Some unexpected behaviors occur and I don't quite understand.
Below is my code:
static void initialize(complex_struct*& infoPtr)
{
complex_struct myInfo;
infoPtr = &myInfo;
// some other codes that modify the contents of myInfo
infoPtr->input_components = 3;
}
static void myfunction()
{
complex_struct* infoPtr = nullptr;
initialize(infoPtr);
std::cout << infoPtr->input_components << std::endl;
}
The output of this is an arbitrary large integer number. But I was expecting an integer 3 is printed.
Restrictions:
I cannot modify complex_struct; it is a third_party struct that needs to be used.
Also, the reason why I need initialize() to be a separate function is that I am doing performance measurement on the memory allocation of complex_struct. So moving the first line of code in initialize() to myfunction() is not an ideal solution.
You are trying to use the pointer to local variable outside of it's scope funciton. In your example, myInfo instance inside initialize() will be deleted after you exit the function, and the address you remembered will be pointing to random garbage memory. You should never use pointers to local variables outside of their scopes.
How to fix the issue? The easiest way would be to ditch the pointer here, and instead pass your struct by non-const reference. Code would look like following:
void initialize(complex_struct& info)
{
// some other codes that modify the contents of myInfo
info.input_components = 3;
}
void myfunction()
{
complex_struct info;
initialize(info);
std::cout << info.input_components << std::endl;
}
There is one subtle flaw in the suggested code: effectively info is initialized twice. First time when it's instance is created (complex_struct info) and the second time inside initialize() function. It would not have any noticeable effect in this example (info is allocated on the stack, and I do not think it has any non-trivial constructor) but might be of bigger problem in other setting. The best way to initialize it in this case would be to return the struct from the initialzer function, and rely on copy-elision to optimize away all the copies. Illustration code:
complex_struct initialize()
{
complex_struct info;
// some other codes that modify the contents of myInfo
info.input_components = 3;
return info;
}
void myfunction()
{
complex_struct info = initialize();
std::cout << info.input_components << std::endl;
}
You are returning a pointer to an object in the stack frame. That object gets deleted when the function returns. You have a dangling pointer in myfunction.
Ways to solve the problem:
Allocate memory from heap
static void initialize(complex_struct*& infoPtr)
{
infoPtr = new complex_struct ;
infoPtr->input_components = 3;
}
Make sure to deallocate the memory in the calling function.
Use an object, instead of a pointer
static void initialize(complex_struct& info)
{
info.input_components = 3;
}
and change its usage:
static void myfunction()
{
complex_struct info;
initialize(info);
std::cout << info.input_components << std::endl;
}

use *this as std::shared_ptr

here is a "chess++" problem that I'm facing wright now with my nested class,
although it may look like some joke, it's not a joke but real problem which I want to either solve or change the way to achieve the same thing in my project.
#include <map>
#include <memory>
#include <iostream>
#include <sigc++/signal.h>
class foo
{
public:
struct bar;
typedef sigc::signal<void, std::shared_ptr<bar>> a_signal;
struct bar
{
bar()
{
some_signal.connect(sigc::mem_fun(*this, &foo::bar::func));
}
void notify()
{
some_signal.emit(this); // how to ??
}
void func(std::shared_ptr<foo::bar> ptr)
{
std::cout << "you haxor!" << std::endl;
// use the pointer ptr->
}
a_signal some_signal;
};
std::map<int, std::shared_ptr<bar>> a_map;
};
int main()
{
std::shared_ptr<foo::bar> a_foo_bar;
foo foo_instance;
foo_instance.a_map.insert(std::pair<int, std::shared_ptr<foo::bar>>(4, a_foo_bar));
foo_instance.a_map.at(0)->notify();
return 0;
}
What I want to do here is to emit a signal.
the signal is declared as one that triggers a handler that takes a shared_ptr as an argument.
the function notify() should convert *this into shared_ptr, how do I do that to make the above code run?
Derive from enable_shared_from_this:
struct bar : std::enable_shared_from_this<bar>
to get a member shared_from_this():
some_signal.emit(shared_from_this());
As long as the current object is owned by at least one shared pointer, this will return a shared pointer, sharing ownership with that pointer. Note that, in your program, a_foo_bar is empty, so neither this nor the call to notify will work. Also beware that it won't work from the constructor or destructor, since the object is not owned by a shared pointer at that time.

Changing pointer to class from one class to another

I'm pretty new to C++ and am having trouble making a pointer point from one class to another. This is what I have, it compiles without error, but doesn't work the way I want it to.
JungleMap *Map;
class JungleMap
{
public:
void goNorth()
{
cout << "You are going north towards the river.\n";
delete[] Map;
RiverMap *Map;
}
}
class RiverMap
{
public:
void goNorth()
{
cout << "You are going north away from the river.\n";
delete[] Map;
JungleMap *Map;
}
}
int main()
{
Map->goNorth();
Map->goNorth();
}
This is what the output is:
You are going north towards the river.
You are going north towards the river.
And this is what I would like the output to be:
You are going north towards the river.
You are going north away from the river.
How do I achieve this? It's really bugging me, especially since it compiles without problems.
Just creating a JungleMap* doesn't create a JungleMap. You formed a pointer, but didn't point it anywhere!
This is particularly dangerous since you then dereference it, and later attempt to delete through it. Yes, this compiles, because a compiler cannot diagnose this in the general case (and is never required to try), but you'll get everything at runtime from silent nothingness, to a crash, to a nuclear explosion.
You are also trying to invoke different functions in two different classes, through changing the type of a pointer (without any inheritance, at that), which is simply not possible and will prevent your code from compiling, even though you've tried to get around it by redeclaring variables locally. I could list a ream of misunderstandings but suffice it to say it's time to read a good introductory C++ book.
I would suggest a combination of inheritance and dynamic allocation, if I knew what you were trying to achieve. A common mistake on SO is to provide nonsense code, then expect us to know what your goal is from that nonsense code; unfortunately we have about as much idea what you really meant to do as the C++ compiler does!
You could make this work (to at least a minimal degree) by creating a base class from which both JungleMap and RiverMap derive. You'd then have a pointer to the base class, which you'd point at an instance of one of the derived classes. You'll also need to rearrange the code somewhat to get it to compile.
class Map {
public:
virtual void goNorth() { cout<<"Sorry, you can't go that way"; }
virtual void goSouth() { cout<<"Sorry, you can't go that way"; }
};
Map *map;
class RiverMap;
class JungleMap : public Map {
public:
void goNorth();
};
class RiverMap : public Map {
public:
void goSouth();
};
void JungleMap::goNorth() {
cout<<"You are going north towards the river.\n";
delete map;
map=new RiverMap;
}
void RiverMap::goSouth() {
cout<<"You are going south towards the jungle.\n";
delete map;
map=new JungleMap;
}
Note: here I'm just trying to say as close to your original design as possible and still have some code that might at least sort of work. I'm certainly not holding it up as an exemplary design, or even close to it (because, frankly, it's not).
What you should do is to sit down and think about the problem you are trying to solve, and make a proper design. In your case you have two "locations", and the "player" should be able to move between these locations. Starting from that we have identified two possible classes (Location and Player) and one behavior (the player can move from location to location).
With the above information, you could do something like this:
class Location
{
public:
void setNorth(Location* loc)
{
north_ = loc;
}
Location* getNorth() const
{
return north_;
}
void setSouth(Location* loc)
{
south_ = loc;
}
Location* getSouth() const
{
return south_;
}
void setDescription(const std::string& descr)
{
description_ = descr;
}
const std::string& getDescription() const
{
return description_;
}
protected:
Location() {} // Made protected to prevent direct creation of Location instances
private:
Location* north_;
Location* south_;
std::string description_;
};
class Jungle : public Location
{
public:
Jungle() : Location()
{
setDescription("You are in a jungle.");
}
};
class River : public Location
{
public:
River() : Location()
{
setDescription("You are close to a river.");
}
};
// The actual "map"
std::vector<Location*> map
void createMap()
{
map.push_back(new Jungle);
map.push_back(new River);
map[0]->setNorth(map[1]);
map[1]->setSouth(map[0]);
}
class Player
{
public:
Player(Location* initialLocation)
: currentLocation_(initialLocation)
{
std::cout << currentLocation_->getDescription() << '\n';
}
...
// Other methods and members needed for a "player"
void goNorth()
{
if (currentLocation_ && currentLocation_->getNorth())
{
currentLocation_ = currentLocation_->getNorth();
std::cout << currentLocation_->getDescription() << '\n';
}
}
void goSouth()
{
if (currentLocation_ && currentLocation_->getSouth())
{
currentLocation_ = currentLocation_->getSouth();
std::cout << currentLocation_->getDescription() << '\n';
}
}
private:
Location* currentLocation_; // The players current location
};
int main()
{
createMap(); // Create the "map"
Player player(map[0]); // Create a player and place "him" in the jungle
// Move the player around a little
player.goNorth();
player.goSouth();
}
In the code above, you have a single player object, which have a "current location". When you move the player around, you simply change the current location for that player. The current location of the player acts as the global Map variable you have.
Note: I'm not saying that this is a good design or code, just that it's simple.
However, if you're truly new to C++, you should probably start with some simpler problems, including tutorials on pointers and inheritance.
You appear to be confusing declaration with assignment.
The following line of code is called a declaration, it tells the compiler the properties and attributes of a thing.
JungleMap *Map;
After this line of code, the compiler knows that "Map" is a symbol (a name) referring to a pointer to a JungleMap.
The compiler doesn't have to do anything with a declaration, unless it would have a side effect, at which point it becomes a definition, which means that the declaration invokes a non-trivial constructor or provides an assignment:
struct Foo {};
struct Baz { Baz() { std::cout << "Baz is here\n"; } };
These are declarations - they don't create instances of objects, they describe the layout and functions for instances. At some point you have to create a concrete instance of them with a definition or a call to new.
struct Foo {};
struct Bar { Bar() { std::cout << "Bar is here\n"; } };
struct Baz {};
int main() {
int i; // no side effects, i is trivial.
char* p; // no side effects, p is a pointer (trivial) type
std::string* sp; // trivial, pointer
Foo f; // trivial
Bar b; // non-trivial, baz has a user-defined ctor that has side-effects.
Bar* bar; // trivial, unassigned pointer type.
Bar* bar2 = new Bar(); // side effects.
Bar bar(); // syntax error, "the most vexing parse"
}
In the above code, we never use "Baz" and we never declare an object of type Baz so the compiler essentially throws it away. Because so many of the variables are trivial and have no side effect, the result of compiling the above will be functionally equivalent to if we had written:
struct Foo {};
struct Bar { Bar() { std::cout << "Bar is here\n"; } };
int main() {
Bar* bar2 = new Bar(); // side effects.
Bar bar(); // syntax error, "the most vexing parse"
}
All of the rest does nothing.
C++ also allows you to re-use names as long as they are in different scopes, but this creates a new, hidden ("shadow") thing:
#include <iostream>
int main() {
int i = 1;
if (i == 1) {
float i = 3.141;
std::cout << "inner i = " << i << '\n';
}
std::cout << "outer i = " << i << '\n';
return 0;
}
The code you wrote will therefore compile, because it is declaring a new and private "Map" inside each of the go functions and then simply never using them.
Note that above I was able to declare i differently inside the inner scope than the outer.
C++ does not allow you to change the type of a variable - in the above code there are two variables called i. When we created the second i, it is a second variable called i the original variable didn't change.
In order to do what you are trying to do, you're going to need to learn about "polymorphism" and "inheritance", C++ concepts that will allow you to describe a "Room" or "Location" and then base JungleMap and RiverMap on that base definition such that you can take a pointer to the core concept, the Room, and write generic code that deals with rooms while moving the specifics of Jungle, River or BridgeMap into specialized functions. But I think that's beyond the scope of a reply here.

How best to pass a reference to a function?

Given the following code:
[example.h]
class MyClass
{
public:
MyClass();
std::string name;
std::string address;
bool method (MyClass &object);
};
[example.cpp]
MyClass::MyClass()
{
}
bool MyClass::method (MyClass &object) {
try {
object.name = "New Name";
std::cout << "Name: " << object.name << " " << object.address << std::endl;
return true;
}
catch (...) {
return false;
}
}
[test.cpp]
#include "example.h"
int main()
{
MyClass myC;
myC.address = "address";
bool quest = myC.method(myC);
}
What is the difference between the way I've called myC.method in main above, and this alternative way of doing so:
MyClass *myC = new MyClass();
bool quest = myC.method(*myC);
Which is better and why?
In both cases you can send the same value but simply stick with current code is better since it's without pointer dereference and new. You need to take care of delete'ing the object once you are finished with it, which I don't think you need here.
And it's better to use MyClass &object const in the method function so that the reference passed in doesn't get changed.
Using new (and dynamic memory allocation in general) is better if you need the object to last longer that the scope of the function it's being called in. If it's just for a known duration the MyClass myC; local scope version is best (because it's simpler to read and maintain).
When using new your object "myC" won't be deleted until you call delete.
However if you just define it as a local object it will get deleted when it goes out of scope:
{
MyClass myC;
myC.DoSomeStuff();
} // It'll be destroyed here