In my program I have a base Object class and a vector. I have an operation that I want to perform on each Object*, however the 开发者_运维问答operation is dependent on the Object*'s most derived class. Therefore, I use the visitor pattern. However, I've found that the visitor pattern leads to a high amount of coupling; whenever I add a new Object derived class, I must change the base Visitor and every class that derives from Visitor.
Is there an easier way to perform an operation on a list of objects based on their run time type that does not lead to such high coupling?
class Object
{
virtual void action() = 0;
/* ... */
};
void objectAction(Object * o) { o->action(); }
int main()
{
std::vector<Object*> v;
std::for_each(v.begin(), v.end(), objectAction);
}
Now just implement action
in each derived class.
I'm going to read between the lines and guess that your most derived objects have member functions that are unique to them and don't exist in any of the other derived objects, which is why you don't want to add them to the base class.
You can use dynamic_cast
to see if a pointer belongs to the most derived class, then call the function if it does.
MyBase * pBase = *iterator;
MyDerived * pDerived = dynamic_cast<MyDerived *>(pBase);
if (pDerived != NULL)
pDerived->UniqueMethod();
any virtual function will do...
Object* obj;
//...
obj->doOperation();
Your abstract base class (call it 'object') provides the abstract implementation framework that each inherited class must implement. You just invoke the proper methods on each instance of the base class. Something like this (in C#, because my C++ is rather corroded, but you should get the idea):
public abstract class Widget
{
public void MandatoryMethod() ; // no method implementation
}
public class FooConcreteWidget : Widget
{
public override void MandatoryMethod()
{
// some concreted implementation
}
}
public class BarConcreteWidget : Widget
{
public override void MandatoryMethod()
{
// another concrete implementation
}
}
...
List<Widget> Widgets = GetSomeWidgets() ;
for ( Widget widget in Widgets )
{
widget.MandatoryMethod() ;
}
That's about all there is to it.
精彩评论