2

I am working on a C++ project, specifically implementing a shunting yard algorithm.

I have a function that creates a vector of shared_ptr's of type super class, but the classes that are being pushed into this vector are all base class shared_ptrs.

I then need to take this vector and pass it into another function and carry out different logic for each element of the vector in a for loop. The logic that I carry out, however, depends on which base class is present in each element of the vector.

So basically what I don't know is how to identify which type of base class is in each element of the vector. When I debug they are all coming out as type super-class.

So generally I'd like to do something like this:

if(vectorElement == baseClass)
{
  //do some logic
}

Or if there is some different method of carrying this out which I'm missing I'd be interested in carrying that out.

François Févotte
  • 19,520
  • 4
  • 51
  • 74
mcraenich
  • 745
  • 1
  • 14
  • 38
  • I can't say I understand you 100%, but are you perhaps looking for `dynamic_cast` or `dynamic_pointer_cast`? – Angew is no longer proud of SO Dec 02 '12 at 19:35
  • both terms base class and super class stand for a class to derive from. derived classes are also called subclasses (subtle difference :-)). so please edit your post to be clear – stefan Dec 02 '12 at 19:45
  • There may be a way of implementing this into my solution but I don't think any ways I can conceive of are viable. – mcraenich Dec 02 '12 at 19:45
  • I think I do actually need to use a dynamic_pointer_cast, but my understanding of how that worked wasn't clear. If someone could explain it well that would be appreciated. – mcraenich Dec 02 '12 at 20:33

2 Answers2

2

There are many solutions to your problem, frankly is the almost most common problem in OOP.

The most obvious is the virtual function doing different things in different classes:

class SuperClass {
public:
   virtual void doSomething(/*someArgsIfNeeded*/) {
      // some base implementation, possible empty
      // or just use pure virtual function here
   }
};

class SubClass : public SuperClass {
public:
   virtual void doSomething(/*someArgsIfNeeded*/) {
      // some base implementation
   }
};

Then use it as follows:

int SomeArgs;
std::vector<std::shared_ptr<SuperClass>> objects;
for (auto it = objects.begin(); it != objects.end(); ++i)
  it->doSomething(/*someArgsIfNeeded*/);

Other more sophisticated solution is to use visitor pattern.


It is considered a bad practice to use casting (dynamic_cast), so always search for more OO solutions than casting, like these two I presented above.

Community
  • 1
  • 1
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • I am not sure that this solution answers my problem. I know that I can call a function specific to the base class from the vector, but I need to identify which class the base class is without using a function call. I am not actually calling any functions from the base class, and I am not able to modify the classes. – mcraenich Dec 02 '12 at 20:24
  • @danner Clarify (present code or something) this description "I have a function that creates a vector of shared_ptr's of type super class, but the classes that are being pushed into this vector are all base class shared_ptrs. "... – PiotrNycz Dec 02 '12 at 21:16
  • @danner I mean which code is your and you are able to modify and which is not yours and you are not able to modify... – PiotrNycz Dec 02 '12 at 21:17
0

Off the top of my head, a simple solution would be to have a function in the base class, that returns an int signifying which class it is. And in each of the derived classes, override this function to return different values. You could use that value to determine which class is being stored in the vector

Edit: And Generally class specific details are to be left in the class, which is the point of polymorphism. Try to do the derived class specific calculations as an overided member function within each class, and use that just to fetch the value forgoing the need for large for loops (for each new derived class) outside.

Nicomoto
  • 473
  • 2
  • 7
  • 15
  • usually it's a bad idea to do such homebrew type IDs. dynamic_cast was invented for this problem – stefan Dec 02 '12 at 19:49
  • Yes this would work. The only issue I have is that I'm working out of someone else's code, and AFAIK I am not able to modify the classes themselves. I could try this solution if all else fails, but if there is a way of doing it without modifying the classes that would be preferred. There is a function in each of the classes called 'is_convertable_from" that returns a boolean depending on whether the class is convertable from the base class. . but I am not completely sure how that works. – mcraenich Dec 02 '12 at 19:50
  • */#define DEF_IS_CONVERTABLE_FROM(type)\ public: virtual bool is_convertable_from( Token::pointer_type const& ptr ) const {\ return dynamic_cast( ptr.get() ) != 0;\ } This is that function. . – mcraenich Dec 02 '12 at 19:55
  • So it turns out that I actually did need to use static_dynamic_casting for this problem. With a SDC you can downcast an object to anywhere down the hierarchy and the cast will only work if the object is a part of the hierarchy. So if I cast a multiplication object to a multiplication object I could use an if statement that said If(multiplicationObject != 0) or operator object where the hierarchy is Operator->Multiplication I could use an if statement that said If(Operator != 0). But anything casted that's not a part of the hierachy would return 0 or empty and would return false in an if. – mcraenich Dec 05 '12 at 18:34