-4

i have the following problem, i have 2 Classes FooClass and BaseClass, and multiple SubClasses of BaseClass.

I want to add these various Subclasses into the same Vector in FooClass, because i am just implementing functions from baseclass, so i can access them through the vector key.

In the following example, each subclass sets the string name of the BaseClass with setName(), and returns it with getName(). Every subclass uses also thisFunctionisforAll() defined in the BaseClass.

The code does compile fine, except if i add vClasses.push_back(thesubclass); So i need help how i can put all these subclasses of BaseClass into the same vector.

I want to iterate through the varius subClasses of BaseClass in the FooClass vector to output their names. Example is in main.cpp

I thought i can add different subclasses to a vector if i they share the baseclass and the vector is type of the baseclass.

Here is the source:

FooClass.h:

#ifndef TESTPROJECT_FOOCLASS_H
#define TESTPROJECT_FOOCLASS_H


#include <vector>
#include "BaseClass.h"

using namespace std;
class FooClass
{
private:
    vector<BaseClass> vClasses;
public:
    void addClassToVector(BaseClass &classToAdd);
    void getNames();
};


#endif //TESTPROJECT_FOOCLASS_H

    FooClass.cpp


    #include "FooClass.h"

    void FooClass::addClassToVector(BaseClass &thesubclass)
    {
        vClasses.push_back(thesubclass);
    }
    void FooClass::getNames()
    {
      for (size_t i; i < vClasses.size(); i++)
      {
        cout << vClasses[i].getName() << endl;
      }
    }

BaseClass.h


#ifndef TESTPROJECT_BASECLASS_H
#define TESTPROJECT_BASECLASS_H

#include <iostream>
using namespace std;
class BaseClass
{
protected:
    string name;

public:
    virtual void setName()= 0;
    virtual string getName()=0;
    void thisFunctionisforAll();
};


#endif //TESTPROJECT_BASECLASS_H

BaseClass.cpp

#include "BaseClass.h"

void BaseClass::thisFunctionisforAll() {
    cout << "Every subclass uses me without implementing me" << endl;
}

SubClass.h


#ifndef TESTPROJECT_SUBCLASS_H
#define TESTPROJECT_SUBCLASS_H


#include "BaseClass.h"

class SubClass : public BaseClass {
    virtual void setName();

    virtual string getName();

};


#endif //TESTPROJECT_SUBCLASS_H

SubClass.cpp

#include "SubClass.h"

void SubClass::setName()
{
    BaseClass::name = "Class1";
}

string SubClass::getName() {
    return BaseClass::name;
}

SubClass2.h
    #ifndef TESTPROJECT_SUBCLASS2_H
#define TESTPROJECT_SUBCLASS2_H


#include "BaseClass.h"

class SubClass2 : public BaseClass
{
    virtual void setName();

    virtual string getName();

};


#endif //TESTPROJECT_SUBCLASS2_H

SubClass2.cpp

#include "SubClass2.h"

void SubClass2::setName()
{
    BaseClass::name = "Class 2";
}

string SubClass2::getName() {
    return BaseClass::name;
}

main.cpp


#include "FooClass.h"

void FooClass::addClassToVector(BaseClass &thesubclass)
{
    vClasses.push_back(thesubclass);
}

void FooClass::getNames()
{
    for (size_t i; i < vClasses.size(); i++)
    {
        cout << vClasses[i].getName() << endl;
    }
}

I think the solution will be simple, but i am experienced in PHP and there i hadn't such issues.

Maexel
  • 7
  • 4
  • What exactly is the problem here? Please also include your attempts to solve your problem. – Yksisarvinen Mar 16 '18 at 14:48
  • Possible duplicate of [Store derived class objects in base class variables](https://stackoverflow.com/questions/8777724/store-derived-class-objects-in-base-class-variables) – Kevin Mar 16 '18 at 14:48
  • It might be that duplicate, but I can't tell because there is too much code for me to see what the problem area is. I'm voting to close because it doesn't have a _minimal_ complete and verifiable example or clear problem statement. – Weak to Enuma Elish Mar 16 '18 at 14:50

2 Answers2

2

You need to use pointers or references. Polymorphism only works in C++ when you're using pointers. You cannot treat a subclass as a superclass unless you're using pointers or references. You'd need std::vector<BaseClass*> to be able to have a container of both the base class and subclass.

Since you're new to the language, I would recommend researching how pointers work.

Gabriel
  • 829
  • 5
  • 12
  • This answer is correct, but to help the OP more it would be good to specifically point to the problem being _slicing_, as described in the answers to this question: [c++ - What is object slicing?](https://stackoverflow.com/questions/274626/what-is-object-slicing) – davidbak Mar 16 '18 at 14:54
  • @davidbak It is worth mentioning, but I don't think slicing is actually the issue here, as the OP says it doesn't compile with the derived instance (as I suspected). Slicing is an issue if you copy from base class views of the object to another base class instance, or you have set up permissive copy operators. – Gem Taylor Mar 16 '18 at 14:59
  • Thanks for the answer with the pointer vector, that solved the issue. I know about pointers, but not about the vector thing. Also thanks for the reference to slicing, i will take a look into it but at the moment all works fine :) – Maexel Mar 16 '18 at 15:02
  • @GemTaylor well yes, it would have been sweeter with actual code on coliru or something that we could look at. But also, sometimes newbies to C++ from other languages without an explicit compile/link/execute cycle are a little unclear about what it means to not "compile". – davidbak Mar 16 '18 at 15:05
0

Containers like vectors contain things directly, not references to things (as found in, e.g., Java - not sure about PHP). If you've got a class Foo then a std::vector<Foo> will contain Foo instances. If there's a class Bar that derives from Foo and you put a Bar into this vector you'll only get the Foo part of it. The rest is cut off, or sliced, as described here: C++ - What is object slicing?. This is the way it works in C++.

Now, you can put pointers into the vector, e.g., a vector<Foo*>. But the vector object won't own the things pointed to (as it would in a language like Java, for example). It'll just be holding pointers. So you have to manage object lifetime separately. This is a main feature of C++. If you want the vector to own the objects you've got to put your pointers in there as a specific type of wrapped pointer, usually std::unique_ptr or std::shared_ptr.

But now you're getting into more complex but absolutely fundamental C++ stuff and you'll need to understand a lot about how ownership and containers work. Still, there are plenty of ways to learn that, I'm sure you know, and Stack Overflow's c++ tag will have a lot of questions on those topics with useful answers for you.

davidbak
  • 5,775
  • 3
  • 34
  • 50