Vector Public in Class - Can't Use in Implementation? - c++

Here's my situation. I have a class in which I have defined a vector publicly, as below:
class TrackObjects
{
public:
vector<MovingObj> movingObjects;
...
etc.
It has a constructor and everything. I have a separate .cpp file with some implementations where I'm trying to use that vector and methods on that vector. As one example, it's part of a condition in a function like so:
if (movingObjects.locX >= x1)
...
etc.
It tells me movingObjects is undeclared, and to first use this function. It's not a function, and to my knowledge, I haven't called it like one/tried to use it like one.
Can anyone suggest why I might be getting this error?
EDIT: locX is a public variable in the another class MovingObj. TrackObj is the class that creates the vector for objects MovingObj creates. Sorry, I really should've specified that. Like so:
class MovingObj {
public:
MovingObj(int inId, int inLocX, int inLocY, int inWidth, int inHeight);
int id, locX, locY,width,height;

Based on what you are telling us, the proper way to access locX would be something along the lines of:
TrackObjects objs;
objs.movingObjects[15].locX = 123.45;
Or, maybe:
if(objs.movingObjects[15].locX >= 15)
{
//do something
}
You can also encapsulate your access method in TrackObjects (put this in your TrackObjects.cpp implementation):
bool TrackObjects::testLocX(int pos)
{
if(movingObjects[pos].locX>=15)
return true;
return false;
};

This is an elementary C++ issue. movingObjects is part of an object. Code that is not part of the TrackObjects class can only access movingObjects by specifying which object's movingObjects you wish to access.
if (someobject.movingObjects.size() > 0)
...
Another issue is that to access such an object from another cpp file you will first have to #include the file that contains the class definition.

Related

Error trying to create map outside of main function. C++

I'm very new to C++ but I am trying to create a map and insert values into it from a class but seem to keep getting an error.
class Album {
public:
map<string,string> albums;
albums.insert(make_pair("rap","Kamikaze")); // This gives the error
};
when i put those same two lines inside the main function, it works without an issue. Like I said I'm very new to C++ so please don't roast me if it's something simple.
(Also, I have map included and using namespace std added)
You are trying to run code in a space where code isn't supposed to be. You can instead write
class Album {
public:
map<string,string> albums;
Album() {
albums.insert(make_pair("rap","Kamikaze"));
}
};
This will run the code every time the class is instantiated, effectively making it the default value for albums.
Class is not a function. Class body can only contain declarations. Executable code may only be in functions (including class methods). For example:
class Album {
public:
map<string,string> albums;
void add_album(string a, string b) {
albums.insert(make_pair(a, b));
// or: albums.emplace(a, b); // if supported
}
};
...
int main() {
...
Album my_album;
my_album.add_album("rap", "Kamikaze");
my_album.albums.insert(make_pair("some", "Thing"));
...
}
No problem its very simple. Below here is a class definition and map that you have declared is its public data member.
Now this Class will act as a prototype for all "Album" objects and all object created will have their own map member.
class Album {
public:
map<string,string> albums;
};
Consider below example,
Album objA; //Object of Album class is created here
//Map being a public member can directly be accessed here
ObjA.albums.insert(make_pair("some", "Thing"));
So instead of calling insert function in class definition you need to do it this way.
Similarly for objectB,
ObjB.albums.insert(make_pair("some", "Thing"));

Using class references to modify public members within another class

Since my last question had too much code in it, I tried to make the simplest example of what I'm trying to do. Take this for example,..
#include <iostream>
using namespace std;
class String
{
public:
private:
};
class ClassTwo
{
public:
int memberVariable;
private:
};
class ClassOne
{
public:
ClassOne (ClassTwo&, String&);
~ClassOne();
private:
ClassTwo& classTwoReference;
String& stringReference;
};
ClassOne::ClassOne (ClassTwo& two, String& string)
: classTwoReference (two), stringReference (string)
{
two.memberVariable = 3;
}
ClassOne::~ClassOne()
{
}
int main()
{
String stringObject;
ClassTwo classTwoObject;
ClassOne classOneObject (classTwoObject, stringObject);
}
In JUCE, which is the API I'm using to code a VST Plugin, there is a string class that JUCE names "String". I'm not sure exactly what the constructor does, but you can use something like this to create a String object.
String newString("string");
The ClassTwo in my case, is the AudioProcessor class which has a public member variable that I can access from ClassOne like this.
two.memberVariable = 3;
The ClassOne in my case, is a custom Component(I named it PixelSlider) that I'm using in my GUI. It uses a slider listener to check the status of a slider and modify the member variable in ClassTwo(AudioProcessor). I can do this fine using the method above, but the issue is that I want to create as many ClassOne(PixelSlider) objects as I need. I want to pass them a String object that tells them what member variable of ClassTwo(AudioProcessor) to modify. Logically, this would be done by passing a reference to a String object with the same string value as the name of the ClassTwo member variable. Like this,...
ClassOne::ClassOne (ClassTwo& two, String& string)
: classTwoReference (two), stringReference (string)
{
two.(string) = 3;
}
This doesn't work in JUCE, but can anybody tell me a way to get this done without having to create a bunch of different classes almost exactly like ClassOne(PixelSlider) that modify different ClassTwo(AudioProcessor) member variables?
If I understand correctly, you're trying to bind a PixelSlider target to a member of AudioProcessor at runtime, which, as you've discovered, can't be done the way you suggest ( two.(string) = 3 ). One way of achieving this binding would be to use the command pattern (http://sourcemaking.com/design_patterns/command/cpp/2).
AudioProcessor could expose a collection of these command objects for each modifiable property ...
AudioProcessorCommand
AudioProcessor::GetCommandByName(String const& properyName) const
{
...
}
... which you can pass to the constructor of PixelSlider. Something along the lines of ...
PixelSlider::PixelSlider(AudioProcessorCommand& command)
: command_{command}
{
...
}
When the PixelSlider's value changes you would invoke the command ...
command_(this->value_);

Passing class pointer in to constructor for class

Working on a collaborative project (was hoping two would be easier than one - how wrong was I...?)
Basically, what we're trying to do is a bit like this:
class first
{
first(int * num);
};
class second
{
second(first * frst);
first * frt;
};
first::first(int * num)
{
}
second::second(first * frst)
{
frt = frst;
}
There is a bit of an issue though, we can't include our Core.h file, since that contains includes to the files we're already including (there is sense somewhere there). Short version is, we're having to do something a bit more like this:
#ifndef PLAYERSTRUCTURE
#define PLAYERSTRUCTURE
// DO NOT INCLUDE CORE IN THIS FILE
class Core;
struct PlayerMem
{
int cid;
int y, x, z;
};
class Player
{
public:
Player::Player(Core * coar);
Player::Player(void);
Player::~Player(void);
};
#endif
The Core class is declared but not defined, will this cause issues if we try to access it from within the Player class, using Core->GetSomething() etc?
Thanks
You're forwarding declaration. It's OK.
When you can use Core->GetSomething() without any compilation error then it means class Core is defined and it's not an incomplete type. So, there is no issue to use it. Just make sure you're passing a valid pointer to Core when constructing Player.
Note: In your code you're passing a pointer to a class type not a reference.

Registering classes/functions/things before main()

Suppose I have a class called Poem.
class Poem{
virtual void recite() = 0;
}
And I have hundreds of .cpp and .hpp files which describe a subclass, like the following
class TheRaven : public Poem{
void recite() { std::cout << "NEVERMORE!" << endl; }
}
And the likes. And in the main function, I'd like to be able to just iterate through every single possible Poem subclasses and call their recite() function. So I made a class:
class PoemRegistry{
std::map<std::string, Poem*> poems;
PoemRegistry& getGlobal(); // returns a static global registry
void register(const std::string& poemname, Poem * thepoem);
};
And then for each poem subclass .cpp file, I put the following.
class TheRavenRegistor{
TheRavenRegistor(){
PoemRegistry::getGlobal().register("theraven", new TheRaven());
}
}
TheRavenRegistor registor();
ninja edit: I put the global class there, forgot about it
Making it easy, I make a shortcut with #define and templates.
Now, the question is, I just heard about the static class initialization fiasco. I suppose this will be immune against it, or is there something I am definitely missing here? Or is there something more elegant that can be used for this purpose?
This is an example for the Singleton design pattern. Don't use a static global, since the initialisation order is undefined across compilation units.
Instead use something like this:
PoemRegistry& PoemRegistry::getGlobal()
{
static PoemRegistry theRegistry; // construction guaranteed when first call
return theRegistry;
}
Make the getGlobal() method static:
class PoemRegistry
{
public:
static PoemRegistry& getGlobal();
...

How can I make an instant-dependant static variabe in a class method?

I have a function in a class the more or less works like so:
class Player {
private:
Object* minions[16]
public:
void Summon(Object* obj);
};
Player::Summon(Object* obj) {
static int i = 0;
if (i == 16)
return;
minions[i] = obj;
i++;
}
The problem arise when trying to use more than one player, like so:
Player playerone;
Player playerthree;
playerone.Summon(new Object("o1"));
playerthree.Summon(new Object("o2"));
o1 is located in playerone.minions[0], as is expected, however, o2 is located in playerthree.minions[1], the Summon() function using the same i variable. Is there a way to make the Summon() function use a static i variable for a single instance, but use separate i variables for each instance? I know I could do something like make a for loop to the first spot in minions[] equal to NULL, or make i a member of Player directly, but I want to know if there is a better way before I do either of those.
Change Object* minions[16]; to a std::vector<Object*> minions;. That way you can just use minions.size() to know how many there are, or minions.push_back(obj); to add one without worrying about array index stuff.
Why don't you simply put i in each Player? I'd rename it something like summonned_minion_count, but that's the actual intent of what you want to do.
Making a local variable static is effectively making it global. You should simply make i a data member of class Player. And probably give it a more descriptive name.
You need to make your i a member variable of Player.
Or even better you could do something like this:
#include <vector>
class Player {
private:
static int const MAX_MINION_COUNT = 16;
std::vector<Object *> minions;
public:
void Summon(Object* obj) {
if (minions.size() < MAX_MINION_COUNT) {
minions.push_back(obj);
}
}
};