Error trying to create map outside of main function. C++ - 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"));

Related

Using polymorphism with vectors in C++. I'm getting errors when attempting to add a pointer to a derived class to a vector of type pointer to Base

I'm new to C++ and could really appreciate some help. I have a Base class and several class types derived from this. I'm trying to use polymorphism to add these derived objects to a vector of type Base class. After spending some time looking into this, it seems as though the recommended way to do this is using pointers. However, when I try and implement this I get an error message (in intellisense) stating that there is no known conversion between the base and derived class types.
I've included some example code for what I'm trying to achieve. Apologies for such a silly / trivial example, but I'm not allowed to show any of the actual code I'm working on. In this example, in the header file I have an abstract base class "Meal", and two types of derived classes : "SingleCourseMeal" and "ThreeCourseMeal". In the "Restaurant" class I have a vector of type unique_ptr<Meal>
In the cpp file I read from file and create a unique_ptr of either a SingleCourseMeal or a ThreeCourseMeal type, depending on the information in the file. I assign the relevant variables to the dereferenced pointer (from information in the file), and finally add the unique_ptr to the unique_ptr vector in the Restaurant object. However, I'm unable to add a pointer to a ThreeCourseMeal or a SingleCourseMeal to the unique_ptr<Meal> vector.
Could anyone advise where I'm going wrong, and/or how best to implement polymorphism like this? (i.e. populating a vector of type Base with Derived objects)
header file:
class Meal
{
public:
String cuisineType;
double prepTime;
virtual void setRecipe() = 0;
};
class MultipleCourseMeal : public Meal
{
public:
Vector<String> courses;
double intervalBetweenCourses;
void setRecipe() override {}
};
class SingleCourseMeal : public Meal
{
void setRecipe() override {}
};
class Restaurant
{
Vector<std::unique_ptr<Meal>> meals;
};
cpp file:
String cuisineType = getCusineTypeFromFile();
double prepTime = getPrepTimeFromFile();
if (numberOfCourses > 1) {
std::unique_ptr<MultipleCourseMeal> meal = std::make_unique<MultipleCourseMeal>();
Vector<String> courses = getCoursesFromfile();
double intervalBetweenCourses = getIntervalFromFile();
meal->cuisineType = cuisineType;
meal->prepTime = prepTime;
meal->courses = courses;
meal->intervalBetweenCourses = intervalBetweenCourses;
Restaurant.meals.push_back(meal);
}
else {
std::unique_ptr<SingleCourseMeal> meal = std::make_unique<SingleCourseMeal>();
meal.cuisineType = cuisineType;
meal.prepTime = prepTime;
Restaurant.meals.push_back(meal); //THIS IS WHERE THINGS GO WRONG
}

Error while trying to use boost::factory

I am trying to use boost factory and I am experiencing the following problem.
All I am trying to do is having a bunch of derived classes to have a mechanism that will be initializing the derived class that is matched with a corresponding string.
To begin with I have the following base class called name NetWorkBlock,
NetWorkBlock.h
class NetWorkBlock {
protected:
typedef boost::function<NetWorkBlock * ()> NetWorkFactory;
//definition of the function that will be used for the factory
public:
NetWorkBlock();
virtual ~NetWorkBlock();
//some basic functionalities that not related to the factory
and thus not mentioned
static std::map<std::string,NetWorkBlock::NetWorkFactory>& f_factory();
//static function that initializes and returns the map
};
NetWorkBlock.cpp
NetWorkBlock::NetWorkBlock() {
} //empty constructor
NetWorkBlock::~NetWorkBlock() {
} //empty deconstructor
std::map<std::string,NetWorkBlock::NetWorkFactory>& NetWorkBlock::f_factory()
{
static std::map<std::string,NetWorkBlock::NetWorkFactory>* ans =
new std::map<std::string,NetWorkBlock::NetWorkFactory>();
return *ans;
} //initialization of map
Moving on here is how I define things in the the derived class BusNetworkBlock (note ofcourse
there are more derived classes expected to be defined later, but in the current moment I work with a single derived class to manage to have things working):
BusNetworkBlock.h
class BusNetworkBlock {
public:
BusNetworkBlock();
virtual ~BusNetworkBlock();
//some basic functionalities that not related to the factory
and thus not mentioned
private:
/* Very small, "fake" class _initializer. Its only meaning is to define a
static member _init that is initialized at the very beginning of the
main(). Hence the constructor is called, and the constructor registers
the BusNetworkBlock class into the (static) NetWorkBlock::f_factory. */
static class _init {
public:
_init() {
NetWorkBlock::f_factory()["LoadCurve"] = boost::factory<BusNetworkBlock *>();
}
}_initializer;
};
BusNetworkBlock.cpp
BusNetworkBlock::BusNetworkBlock() {
} //empty constructor
BusNetworkBlock::~BusNetworkBlock() {
} //empty deconstructor
/* The definition of the bodies of the funcionalities of the class that are not mentioned here since they are not connected with the factory */
BusNetworkBlock::_init BusNetworkBlock::_initializer;
/* Ensure that the static member _initializer is initialized, so that
BusNetworkBlock is registered into NetWorkBlock::f_factory. */
Now in an other separate class under the name UCBlock I try to use the factory in order to initialize properly the derived NetworkBlock class based on a string I receive in the following way:
UCBlock.h
class UCBlock {
public:
UCBlock(std::istream& inStream); //the received instream
virtual ~UCBlock();
//some basic functionalities that not related to the factory
and thus not mentioned
NetWorkBlock * Network; /*defining a pointer of the base class NetWorkBlock
that want to initialize properly via the factory */
};
UCBlock.cpp
UCBlock::UCBlock( std::istream& inStream ) {
inStream >> network; //setting the string of network the corresponding factory
Network = NetWorkBlock::f_factory()[network](); // set the corresponding object via factory **here is where the problem arises**
}
And the problem arises when I try to use the factory to proper initialize the
derived class of NetWorkBlock. I receive the following error:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_function_call> >'
what(): call to empty boost::function
Aborted (core dumped)
Now I have ofcoruse tried to check this thing online but didn't manage to come up with a solution and that's why I would really appreciate any kind of help here, since I am really stacked here. (Note also that I checked that the string I receive is correct and matches with "LoadCurve").

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_);

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

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.

How to store data what needs to be accessible by all members?

I have the following problem (just learning OOP style C++): I have 3 classes:
app
objectManager
object
The app class sets up startup variables and creates an instance of objectManager. It tells objectManager to load values from different files and to precalculate some data in a vector what will be required for each object.
My problem is the following: I would like to use a precalculated vector accessable for each object. I don't understand how can I possibly access this variable from the objects, as they know absolutely nothing about the manager's instance.
I've read about singletons but I have no idea how should I implement it.
I've read about static data members but AFAIK it seems that I still have to somehow connect to the objectManager instance, so it doesn't help me.
I've tried global variables (I know...), but ended up with compiling errors.
I've tried to put static variables outside of a class definition in objectManager.h (is it a global case?), and I ended up with something strange:
I can access the variables from all parts of the program what includes objectManager.h, but it's value is different/uninitialized in different classes.
objectManager.h
#pragma once
#include "Object.h"
static int xxxtest;
class objectManager
{
objectManager.cpp
xxxtest = 123456;
cout << xxxtest << endl;
-> 123456
while in object.cpp or app.cpp (after)
cout << xxxtest << endl;
-> 0
Can you explain to me what is happening here?
Can you recommend me a simple and clean way of organizing such a program, while making a precalculated variable accessable to other parts of the program?
Static class variables are in fact the solution.
Static variables in classes need to be declared in the CPP file, right after the include.
Header:
class Class {
static int staticVariable;
static void staticFunction();
//...
};
CPP:
int Class::staticVariable = 5;
Do that, and all Object instances have access to the static variable (if it's private) and all members of the entire Program can access it (if it's public) by stating:
int Value = Class::staticVariable;
I hope this helps shed some light.
Ah yeah, I used the code from http://de.wikibooks.org/wiki/C++-Programmierung:_Statische_Elemente_in_Klassen (Page is in German) as Reference.
To get back to your problem, that would mean:
Header:
class objectManager {
static std::vector<double> Precompiled;
};
CPP:
std::vector<double> Precompiled; //Initialized automatically.
Since you only intend to create one objectManager, it is a candidate for a singleton or a regular global. As a global, you could define a header file like this:
// in object_manager.hpp
class App;
class ObjectManager;
class ObjectManagerImpl;
ObjectManager & objectManager ();
class ObjectManager {
friend ObjectManager & objectManager ();
friend class App;
std::unique_ptr<ObjectManagerImpl> impl_;
ObjectManager ();
void read_files (std::string file1, std::string file2);
public:
std::vector<int> & precomputed ();
//...
};
And in your source file, you could have something like:
// in object_manager.cpp
class ObjectManagerImpl {
friend class ObjectManager;
std::vector<int> precomputed_;
//...
};
ObjectManager::ObjectManager () : impl_(new ObjectManagerImpl) {}
void ObjectManager::read_files (std::string file1, std::string file2) {
//...
}
std::vector<int> & ObjectManager::precomputed () {
return impl_->precomputed_;
}
//...
ObjectManager & objectManager () {
static ObjectManager instance;
return instance;
}
Now, in the source file of your object, you would include the header file for objectManager, and access the vector through the accessor.
// in object.cpp
//...
std::vector<int> &precomputed = objectManager().precomputed();