List of Uninitialized Objects - c++

So here is my goal, I would like to instantiate an object based on a string and an integer. My current thought was this:
1) Create a list of possible objects
2) Each object has a static method that takes a string and integer and returns true, if what was passed matches the static members that object.
3) Then iterate over the list of possible objects, call the static function of that object if it returns true then instantiate that particular object:
pseudocode:
// Pseudo Definitions
class CoolObject
class CoolObject2: public CoolObject ....
class CoolObject3: public CoolObject ....
// List of Objects
std::list<CoolObject> list_of_possible_objects;
list_of_possible_objects.push_back(CoolObject);
list_of_possible_objects.push_back(CoolObject2);
list_of_possible_objects.push_back(CoolObject3);
// Inside of the matching function
for (std::list<CoolObject>::iterator it=list_of_possible_objects.begin(); it != list_of_possible_objects.end(); it++) {
if(*it::is_cool_object(string, int)) {
return *it(string1, string2); //Assume the constructor takes some objects that were passed into the function
}
}
However, this seems like a dream since C++ does not allow to have objects that are not instantiated.
I am sure I can do this with some kinda map and a switch statement but this seemed lot more elegant in my head so I went for it first.
Is there any pattern out there that is similar to this, that I can follow? Or is there a way to make what I am asking be legal?
I would rather not maintain a huge map and I would rather just have a list of objects and ask each object if its the one and then instantiate, if having a huge map and a switch statement is the only way, thats fine. I thought maybe ask some gurus, if this is possible or is there a better way of doing it before giving up on this way.
Thanks for all the help!

Store std::optional<T>, that's probably what you're looking for: basically just a flag to tell if the object is constructed and a reference to the object iff constructed. Note that you can't spare the flag, as you need to know whether to run the destructor or not.

Related

c++ passing objects to functions

I am working on a project dealing with many different operations with sets. I have a specific question about passing by reference. In the header file I have created an object called SoS which stands for set of strings and its private data members are a vector of strings called m_vos and a boolean called m_cofinite. Here is an example of my confusion with the intersection function I am creating.
SoS::makeIntersection(const SoS& B) const {
}
This is the function I am creating and It needs to create an intersection of the sets. I would approach this by looping through and putting both sets together and then removing elements that arent a part of both original sets therefore giving me the intersection of the two. I know logically how i could do this but I am confused as to what I am passing into the function and how I am able to use two sets when only one appears to be passed in(I was told I can not change the structure of the function so it needs to be this way). Any help is greatly appreciated.
The first set is this and you access its members like this->m_vos.... The second set is the one you passed in and you access its members like B.m_vos....
However, for brevity, you can omit the this-> unless there is a name conflict between a local variable and a member variable. So you can do simply m_vos... and B.m_vos....
Also you need to consider what your function will return? Maybe the intersection you create? That would be a third SoS variable that you might return as a result:
// return type SoS
SoS SoS::makeIntersection(const SoS& B) const {
SoS intersection; // this is the new SoS that will be the intersection
// fill intersection.m_vos using B.m_vos and this->m_vos
return intersection; // return the intersection version
}
The object on which you called the function can be accessed through this. The second object is the argument to the function.
The first vector of strings is this->m_vos.
The second vector of strings is B.m_vos.
Your statement:
I was told I can not change the structure of the function so it needs to be this way
does not make sense to me.
The function does not seem to have a return value. Did you forget to include it in the posted code? How will the resultant object, the intersection, be returned to the calling function?
You cant' modify this to be the resultant object since the function is a const member function.
You cant' modify B to be the resultant object since it is passed by const&.
The way to call member functions for a class is through its objects(if not static). To get the intersection of two sets(sos objects) you'll call the function using one of the SoS object and pass the other one as the parameter reference.
Inside the member function the object which you've used to call it can be derefenrence using this pointer. Read more here and here.

Basic understanding of pointers

I am doing some assignment and i am not good at understanding pointers. Please help me understand what argument i need to pass to this function.
void City::setList(List<City*> *l){list = l;}
Without seeing the definition for List (and because Google is case-insensitive), I can't give an exact answer, but you'll want to construct it something like this:
List<City*> myList;
Then (assuming List works like Java's List):
City c; //Or with constructor, or whatever
myList.add(&c);
To call your method:
// `d` is some other City
d.setList(&myList);
There's one major caveat, though: Unless you created c with new (which, given the syntax example I used here, you probably didn't), any pointers to it are going to be dangling as soon as c goes out of scope. You'll want to make sure you aren't doing that. And if you create it with new, you have to be sure to delete it later.

Returning a reference to a mapped value that is not a pointers

I think it'll be better if I show my code first, then explain my problem.
std::map<std::string, SManager> m_managers;
//SResourceManager is derived from SManager
SResourceManager& getResourceManager() { return m_managers["resource_manager"]->second; }
What I'm trying to do is return a reference from a SManager (which would be the copy of SResourceManager) to be able to use elsewhere. I know I can use things like std::shared_ptr, but I'd prefer not to use pointers in this situation because I want the SResourceManager within the map to possibly change, but stay in there. Is there a way to cast this to a value that I can actually return?
Thanks
"SResourceManager is derived from SManager". Going from a base type to a derived type will require an explicit cast.
However, you have a bigger problem. Your map contains SManager objects directly. As a consequence it does not and can never contain SResourceManager objects or any other derived type. Whatever code you've written to populate that map is most likely ending up slicing off the derived portions.
If you want to have things in terms of a base type that could actually refer to objects of derived types then you need to use pointers in some manner. unique_ptr or shared_ptr are reasonable options.
So you might end up with something like:
std::map<std::string, std::unique_ptr<SManager>> m_managers;
SResourceManager& getResourceManager() { return *static_cast<SResourceManager*>(m_managers["resource_manager"].get()); }
It looks like you are using incorrect syntax. If to suppose that type SManager is declared as pointer to a polymorphic class then the function will look the following way
SResourceManager& getResourceManager() { return *m_managers["resource_manager"]; }

How do I allocate memory within this function?

I have the following function and a hierarchy of classes such that Multinumber is inherited by Pairs, Rational, and Complex. All of these share functions which are virtual in Multinumber. My problem is the following code. The way it is written right now, the newElement variable goes out of scope when it is added to my setArray which is of type Multinumber**, and I need to figure out some way to allocate memory within this function. Oddly, paramters that are passed into the function, even when printed on the first line, are always empty when I do a cout<<newElement->tostring(); Can anyone tell me what is wrong here?
bool Set::addElement(Multinumber* newElement)
{
bool success = false;
if(isFull())
{
resize();
}
if(!isMember(newElement))
{
setArray[numElements] = newElement;
numElements++;
success = true;
}
return success;
}
EDIT: Yes the poster is correct, this is a homework assignment
To avoid memory troubles replace Multinumber** setArray with std::vector<boost::shared_ptr<Multinumber>> setArray.
In the real world (I understand from your previous question that this is for homework), you wouldn't implement your own set. The standard library provides this functionality (std::set if you want to keep the elements in order; std::unordered_set if you're using C++0x and/or have the appropriate extensions, and prioritize speed over the additional functionality).
You should probably also look into some smart-pointer classes.
That said:
In your code, newElement isn't going out of scope. What happens is that you've been given a pointer to the calling code's data, and the calling code is then letting the pointed-at thing go out of scope.
As I responded to your previous question, you need to use the "virtual clone idiom" to make the copy.
Basically, you want to call new with whatever the type is of the passed-in, pointed-at thing, in such a way that a copy is made. To ensure "that a copy is made", the natural thing to do would be to use the copy constructor with new, that is new whatever(my_existing_whatever_instance). But in C++, constructors cannot be virtual, so we can't actually put the desired type into a new call. Instead, we have to fake it with a member function. Since member functions can be virtual, the correct version clone is looked up in the actual pointed-at thing, which is implemented to call new using its own type, and calling its own copy constructor. The link provides details.
If you need it to grow, make it of type vector<Multinumber*> and use setArray.push_back(newElement).
You need to make sure that the caller keeps the element alive as long as the vector is alive. If not, perhaps add a virtual Clone method to Multinumber that returns a copy (and subclasses implement it). Then, push_back(newElement->Clone()).

C++ Set object member as reference/pointer of member of a different object?

(I'm not sure if that title is worded correctly, as I'm still new to C++)
I have two classes, loosely represented here:
class SuperGroup
{
public:
LayoutObj theLayout;
}
class SomeClass
{
public:
LayoutObj myLayout;
SuperGroup myGroup;
}
During SomeClass's constructor, I want to set myGroup.theLayout to be pointing to SomeClass's searchLayout. Something like this:
SomeClass::SomeClass()
{
myGroup.theLayout = &myLayout;
}
Am I doing this correctly? Or do I need to be using a pointer? My code seems to compile okay, but when I execute it, it crashes, and I can tell its something to do with this assignment. Also, I'm not sure if its incorrectly coded, or if the SDK/API I'm using simply doesn't like it.
The reason I'm trying to reference myLayout with SuperGroup is because I have many methods in SuperGroup that need to use myLayout from SomeClass. I'm simply trying to avoid having the pass myLayout by reference into those methods every single time. Make sense? Is there an easier way to accomplish this?
You do indeed need a pointer. Try using:
LayoutObj *theLayout;
Without a pointer, you are trying to assign a LayoutObj to a memory address. This may compile, but is not the behavior you want. Instead, you need a pointer to point to the memory address of a LayoutObj.
The line myGroup.theLayout = &myLayout; remains the same.
As always is the case with C++, be careful that myLayout does not go out of scope before theLayout. If this happens, you have a dangling pointer. If there is any risk of this, consider using a smart pointer of some kind, or otherwise modify your design to accommodate this.
Yes, you would need to use a pointer: LayoutObj *theLayout;
In reference to your last paragraph, I would consider the some alternative designs, such as:
Requiring that the LayoutObj is passed into each method of SuperGroup, therefore decoupling the particular LayoutObj acted upon from the actions that can be performed, or
Moving those methods to SomeClass, if they're not needed elsewhere, or
Making them methods of LayoutObj itself.