So, here's my problem: I have a superclass:

Class SuperClass {
    virtual someMethod() = 0;
}

... and then I have multiple classes that inherit SuperClass. Now, if I want to put objects made from the subclasses to a single vector<SuperClass>, how could I get the abstract function to work? I mean, it does, if I leave the "= 0" part out and make an implementation of the function for the SuperClass, but what I need is an abstract SuperClass. This would work fine otherwise, but I want to store all types of subclasses in one vector. Impossible or not? :P

Like this ?

class super  {
    public:
        virtual void disp()=0;
      };

class sub : public super  {
   public:
       int x;
       sub (int s) : x(s) {}
       void disp() {std::cout << x;}
      };
int main ()  {
        std::vector <super*> d;
        sub a(5);
        d.push_back(&a);
        (*d.front()).disp();
      }

caut_baia: Exactly like that, but the problem is, that doesn't compile. It says one can't make a vector of "supers" because it's abstract.

EDIT:
Oops, I didn't notice you made a pointer vector there. I tried that and it did work for the problem. There's just a teeny, tiny problem of the code being hundreds of lines long and the vector is already used there as a non-pointer vector, which results in lots of changes. Is there a way to do that without using a pointer vector?

Edited 6 Years Ago by bleedi: n/a

Does SuperClass have to be abstract?

Yeah, for ensuring that all the subclasses declare the needed functions.

I've got it working for that part now (with the pointer vector, did some refactoring), but I have a bit of a problem with iterating the vector. For example...

vector<SuperClass*>::iterator begin = testVector.begin();
vector<SuperClass*>::iterator end = testVector.end();
            
for( ; begin != end; *begin++) {
    begin->someMethod();   // problems...
}

Inside the for loop, if I try to use any methods of the subclasses, it crashes. I've tried changing the way the method is reached: begin->someMethod(), (*begin).someMethod(), (*begin)->someMethod()... They all end up either crashing or giving a compile error about method not being declared. If I got it right, I should double dereference the pointer to get on the actual object?

Edited 6 Years Ago by bleedi: n/a

caut_baia: Exactly like that, but the problem is, that doesn't compile. It says one can't make a vector of "supers" because it's abstract.

EDIT:
Oops, I didn't notice you made a pointer vector there. I tried that and it did work for the problem. There's just a teeny, tiny problem of the code being hundreds of lines long and the vector is already used there as a non-pointer vector, which results in lots of changes. Is there a way to do that without using a pointer vector?

there's no way to do it without using a pointer vector because if you want to do otherwise and push a copy of objects into vector, all objects existing in the vector should be of same class assuming that class is not abstract.

Edited 6 Years Ago by Garrett2011: n/a

Yeah, for ensuring that all the subclasses declare the needed functions.

I've got it working for that part now (with the pointer vector, did some refactoring), but I have a bit of a problem with iterating the vector. For example...

vector<SuperClass*>::iterator begin = testVector.begin();
vector<SuperClass*>::iterator end = testVector.end();
            
for( ; begin != end; *begin++) {
    begin->someMethod();   // problems...
}

Inside the for loop, if I try to use any methods of the subclasses, it crashes. I've tried changing the way the method is reached: begin->someMethod(), (*begin).someMethod(), (*begin)->someMethod()... They all end up either crashing or giving a compile error about method not being declared. If I got it right, I should double dereference the pointer to get on the actual object?

I believe your code should be as it follows:

vector<SuperClass*>::iterator begin = testVector.begin();
vector<SuperClass*>::iterator end = testVector.end();

for( ; begin != end; begin++) {
(*begin)->someMethod();
}

you have problems understanding what an iterator is I assume, go here or here and take a look, it will help you for sure.

Edited 6 Years Ago by Garrett2011: n/a

@Garrett: >>there's no way to do it without using a pointer vector
For the record, Nothing is impossible in C++:

class SuperClass {
  public:
    class Impl {
      public:
        virtual void someMethod() = 0;
        virtual Impl* clone() throw() = 0;
        virtual ~Impl() throw() { };
        SuperClass Encapsulate() throw() { return this; };
    };
  private:
    Impl* pImpl;
    SuperClass(SuperClass::Impl* aImpl = NULL) throw() : pImpl(aImpl) { };
  public:
    void someMethod() { pImpl->someMethod(); };
    ~SuperClass() throw() { delete pImpl; };
    SuperClass(const SuperClass& aObj) throw() : pImpl(aObj.pImpl->clone()) { };
    SuperClass& operator =(const SuperClass& aObj) throw() { pImpl = aObj.pImpl->clone(); return *this; };
};

class SubClass1 : public SuperClass::Impl {
  public:
    virtual void someMethod() { .. };
    virtual Impl* clone() throw() { return new SubClass1(*this); };
    SubClass1(const SubClass1& aObj) throw() : ... { ... };
    ...
};

int main() {
  std::vector<SuperClass> objects;
  objects.push_back((new SubClass1)->Encapsulate());
  ...
};

Edited 6 Years Ago by mike_2000_17: n/a

you have problems understanding what an iterator is I assume, go here or here and take a look, it will help you for sure.

Actually, I do understand iterators. The way you described I should do leads to crash as I already told in my previous post. For now I've refactored all the subclasses so I can implement the needed functions in the SuperClass, thus making the abstract SuperClass obsolete. Still, I'm getting some weird crashes (segmentation faults) which I've traced outside from the class structure into another. I guess it might be a totally different bug from the other parts of the code, but it just might be that something's got mixed up in the main structure and the bug is transferred outside, where it crashes...

Well, I gotta check this out for a moment and come back if I can't find the reason(s). :)

Edited 6 Years Ago by bleedi: n/a

Now I've figured out the weird segmentation fault problems. It turned out that now the main code was working and the other parts got executed, there was a little typo there which caused one of the iterators go off-limits.

I'm still having weird crashes if I use the pointer vector. When trying to iterate, it crashes on this:

if(!testVector.empty()) {
    vector<SuperClass*>::iterator begin = testVector.begin();
    cout << "Type: " << (*begin)->getType() << endl;
}

It crashes on the getType() method call. I have no idea where to look up for this, since the getType() method only returns a string and works flawlessly in the other parts of the code when it's called outside from a vector.

Edited 6 Years Ago by bleedi: n/a

Now I've figured out the weird segmentation fault problems. It turned out that now the main code was working and the other parts got executed, there was a little typo there which caused one of the iterators go off-limits.

I'm still having weird crashes if I use the pointer vector. When trying to iterate, it crashes on this:

if(!testVector.empty()) {
    vector<SuperClass*>::iterator begin = testVector.begin();
    cout << "Type: " << (*begin)->getType() << endl;
}

It crashes on the getType() method call. I have no idea where to look up for this, since the getType() method only returns a string and works flawlessly in the other parts of the code when it's called outside from a vector.

according to your code there, there would be two situations in which a crash might occur:
1-the pointer you get by the expression "(*begin)", doesn't point to a right part of the memory and is not valid.
2-the pointer you get by the expression "(*begin)", does point to a right part of memory but the crash happens when the function called by expression "(*begin)->getType()" is running.
so take these into consideration.

Edited 6 Years Ago by Garrett2011: n/a

according to your code there, there would be two situations in which a crash might occur:
1-the pointer you get by the expression "(*begin)", doesn't point to a right part of the memory and is not valid.
2-the pointer you get by the expression "(*begin)", does point to a right part of memory but the crash happens when the function called by expression "(*begin)->getType()" is running.
so take these into consideration.

Actually, it was both. :P I had wrote some really unthoughtful code back there, and in one part I had a semi-complete function which was left unfinished because some other problems had arisen.

This article has been dead for over six months. Start a new discussion instead.