Hi, if anybody has a second, I have a quick question:

In the following situation, Container can contain any combination of the derived classes. If I wanted to go through "Container", for example, and delete all instances of the class DerivedC, how would I do that?

class Base;
class DerivedA : public Base;
class DerivedB : public Base;
class DerivedC : public Base;
...

std::vector<Base*> Container;

The only idea I have come up with is to add an "int type" variable to "Base" that gets set in the constructor of each derived class, so that I know which is which. Isn't there a more elegant way of doing something like this though?

Thanks for any help.

Recommended Answers

All 3 Replies

You might want to try to use Run-Time Type Identification. The <typeinfo> header is useful for this. I'm not sure how well it will work because you're using it on a pointer to a subclass though.

The function you'll want is typeid(), but it's rather obscure and really not very well documented (at least not where I linked).

Here is an example code that works on VS2008, I don't know how well it will work on other compilers:

#include <iostream>
#include <typeinfo>

class A {
};

class B : public A {
};

class C : public A {
};

int main() {
  C myObj1;
  B myObj2;

  if (typeid(myObj1) == typeid(::C))
    std::cout << "The types match." << std::endl;
  else
    std::cout << "The types don't match." << std::endl;

  std::cout << std::endl;

  if (typeid(myObj2) == typeid(::C))
    std::cout << "The types match." << std::endl;
  else
    std::cout << "The types don't match." << std::endl;
  std::cin.get();
  return 0;
}

It doesn't use a pointer to a sub-class though.

Yes there is.

First of all, your solution of adding an int variable to the Base class that the most derived class will set upon construction is a very basic form of RTTI (Run-Time Type Identification). But, C++ already has RTTI, and it can be used in two ways, via typeid() and via dynamic_cast. Both require that you have at least one virtual function in your classes (which you should, since the destructor of the Base class has to be declared virtual, if you are going to derive the class). So here is an example:

for(std::vector<Base*>::iterator it = Container.begin(); it != Container.end(); ++it) {
    DerivedC* ptr = dynamic_cast<DerivedC*>(*it);
    if(ptr) {       //if ptr is non-NULL, then the cast succeeded and *it is a DerivedC object.
      delete ptr;   //Delete the object.
      it = Container.erase(it); //and erase it from the list (and reset the iterator).
      --it;
    };
  };

This can also form the basis of the Visitor Pattern in OOP (not to be confused with the Visitor Pattern in GP, which is far more powerful). I personally am not a fan of the OOP Visitor Pattern, but it can be useful sometimes.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.