0

I need to store different types of objects in a single container. All the objects that go in the container will have a void continueExecution() function with the same purpose, but the implementation is totally different.

I found this question to be very helpful Objects of different classes in a single vector?. I tried to implement the answer, but c++ is crushing me. Can you please suggest how to call the derived functions rather than the base functions after getting the object from std::vector? I was really hoping that any calls to base.continueExecution() would call derived.continueExecution(). please see below:

Base class: - I created a base class strictly to make all my classes with the same function name be the same type. I will never create an object out of this class. The base class header file:

class DelayCommandBase
{
    public:
        DelayCommandBase();
        void continueExecution();
};

The cpp file for the base class is just a print statement, and if it’s running that is bad for me (and it is running):

void DelayCommandBase::continueExecution() 
{
    Serial.println("DelayCommandBase continueExecution function... why is c++ so hard?!");
}

Derived class - I have a bunch of these types of files, lets stick to tst.h with a TST class. :

class TST : public DelayCommandBase
{
    // …code...
    public:
    void continueExecution();
    //…code...
};

The derived class .cpp file is implementing the continueExecution() and a bunch of other functions. I don't think the issue is there.

A third class - this is what manages many objects that are constructed using the derived classes. In the header file I am creating a vector of base type. I think this is how I can store all the derived classes in a single container (assuming I don't use boost, which I don't want to use). Header file:

private:
    std::vector<DelayCommandBase> midFlightCommandObjects;

In the .cpp file (all in a single function) an object is created from a derived class, is started via a function call, and is stored:

int hardwarePin = 13;
int delay = 1000;
TST tstCommandObj(hardwarePin, delay); //a working object... Yay

//the object is executed, and all is so happy so far:
tstCommandObj.start();

//Then I store it in the vector of base type:
if(tstCommandObj.commandIsFinished() == false)
{           
    midFlightCommandObjects.push_back(tstCommandObj);
    Serial.println("TST object saved");
}

So far no issues. Now in a different function, in the same manager class I try the following:

midFlightCommandObjects.at(i).continueExecution();

and the function in the base class runs, not the derived class with the implementation. I tried making the function virtual, but that didn’t fly. I tried using instead of . but that gave errors that bend my mind. I tried passing the derived class as a pointer to the base class object and that didn't do anything different. I am not a programmer, and c++ is crushing my belief that I am a competent human. What do I need to do to call the derived class instead of the based class once I pull the objects out of the container?

Mike
  • 371
  • 1
  • 4
  • 18
  • 1
    If you are going to override a function in a derived class it must be marked virtual in the base class. `class DelayCommandBase { public: DelayCommandBase(); virtual void continueExecution(); };` You probably also want a virtual destructor. – Jerry Jeremiah Jan 24 '21 at 20:36
  • In the example you followed did you not see that the vector was a vector of **pointers**. i.e. `std::vector midFlightCommandObjects;` not `std::vector midFlightCommandObjects;` That's where your mistake is. – john Jan 24 '21 at 20:39
  • 1
    Because you have a vector of the base class, all your objects are getting converted to the base class when you add them to the vector. This is why the base class method is running. This is called *object slicing* if you want to research it more. – john Jan 24 '21 at 20:42
  • @JerryJeremiah I tried that, but it didn't fly. same result. – Mike Jan 24 '21 at 20:42
  • @john That is something I didn't notice, and didn't try. that is likely where I messed up. Let me try that... – Mike Jan 24 '21 at 20:42
  • @Mike You need both my fix and Jerry's. – john Jan 24 '21 at 20:43
  • the dupe explains what happens with your code, but does nothing to help you with what you want to achieve. Since the question is closed, here it is in the comments: you need polymorphism. For polymorphism to work in C++ you need a couple of things: virtual methods and a pointer of type Base to an actual object of type Derived. I will cook really fast an example for you. – bolov Jan 24 '21 at 20:43
  • @bolov thank you! I am really having a hard time with C++. I think if I go to hell, I will be given the traveling salesman challenge that has to be solved in C++. – Mike Jan 24 '21 at 20:49
  • https://godbolt.org/z/ezh375 and reply to me if you need help with the example – bolov Jan 24 '21 at 20:55
  • just a curiosity: `Serial.println` suggest your program runs on Arduino, but all the Arduino toolchains I know don't have the standard library (you can't use `std::vector`). So if you program for Arduino can you please tell me how you can use `std::vector`? – bolov Jan 24 '21 at 21:07
  • @bolov Thanks a ton for the example... That's incredible! Thank you!! The arduino was done via: https://github.com/mike-matera/ArduinoSTL it allows the use of the standard library. – Mike Jan 24 '21 at 21:23
  • @bolov I am having an issue with private members in the derived object after retrieval from the container. Could you please take a look? https://godbolt.org/z/EWYveq – Mike Jan 25 '21 at 12:49
  • @Mike without a [MRE] there's not much I can do. The only thing I see is that `m_commandIsFinished` is not initialized. Make sure you initialize the data members in the constructor. – bolov Jan 25 '21 at 13:12
  • @bolov It is initialized in the derived constructor. I'm trying to wrap my mind around this: https://stackoverflow.com/questions/2436125/c-access-derived-class-member-from-base-class-pointer – Mike Jan 25 '21 at 13:20
  • @Mike create a [MRE] with what you are tying to achieve and I'll take a look at. – bolov Jan 25 '21 at 13:22
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/227805/discussion-between-mike-and-bolov). – Mike Jan 25 '21 at 16:24

0 Answers0