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.

Dani AI

Generated

The thread already points to the right ideas. ’s instinct to tag objects by type is workable but fragile; ’s note about RTTI/typeinfo and ’s dynamic_cast example are both relevant. Dynamic type checks are the usual, clean way to identify DerivedC objects at runtime—just avoid manual ownership mistakes.

A safer, modern approach is to make the container own the objects and let RAII do the deletes. Store std::unique_ptr<Base> (or another smart pointer that matches the ownership model) in the std::vector, then remove matching elements with the erase–remove idiom. Example:

std::vector<std::unique_ptr<Base>> container;
// ...
auto it = std::remove_if(container.begin(), container.end(),
    [](const std::unique_ptr<Base>& p) {
        return dynamic_cast<DerivedC*>(p.get()) != nullptr;
    });
container.erase(it, container.end());

This avoids explicit delete calls and double-deletion bugs. It also keeps lifetime clear: removing an element lets its unique_ptr destructor free the object automatically.

Important caveats and alternatives:

  • RTTI (dynamic_cast/typeid) only works for polymorphic classes — make Base polymorphic (a common choice is a virtual destructor).
  • Erasing from std::vector invalidates iterators after the erase point; the erase–remove idiom handles that correctly.
  • If performance is critical or RTTI is undesirable, consider a design alternative: maintain per-type containers at insertion time, add a small virtual query method on Base implemented by derived classes, or use a Visitor-like interface to let objects self-identify without casting.
  • If multiple owners exist, prefer std::shared_ptr and a matching removal strategy.

Summary: prefer smart pointers + erase–remove with dynamic_cast when occasional type-based removal is needed; avoid integer type-tags unless there is a proven performance/portability requirement.

Recommended Answers

All 3 Replies

You might want to try to use Run-Time Type Identification. 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 and via . 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.