samedi 19 avril 2014

c ++ - appel de fonction substituée de la fonction de substitution - Stack Overflow


Suppose I have virtual function foo() in class B, and I need slightly different behavior in one of B's derived classes, class D. Is it OK to create an overriding function D::foo(), and call B::foo() from there, after the special case treatment? Like this:


void D::foo()
{
if (/*something*/)
// do something
else
B::foo();
}

I am not asking whether that would work, I know it will. I want to know, whether it is right in terms of a good OOD.




This is perfectly good. In fact, the canonical way of performing some operations is calling the base class method, then do whatever (or the other way around). I am thinking of operator= here. Constructors usually work that way, too, even if this is a bit disguised in the initialization list.




Yes, it is.




Yes, its totally ok as long as you are not violating the Liskov Substitution Principle.




I have seen GUI frameworks use this to fall back on the base class's default implementation which contained code to signal errors/throw an exception/return a generic value.




It's ok. Syntax you had gave can be also used to temporary turn off polymorphism, i.e. when you call obj->B::foo() method will be chosen from class B regardless if foo() is virtual or not and if obj is instance of B or not (it must be an instance of class extending B though).




Yes it is , that's what your compiler do for you every time it generates a constructor and a destructor: calling the mother's one for instance. I often rely on that"trick" in my own code.




It's fine to call base's implementation, but doing it conditionally moves you apart from constructor semantic, contrary to what have been suggested in other answers.


You may run into fragile base class issue in two ways :



  • By assuming B::foo() provides common behavior for the whole hierarchy (ie, forgetting the method isn't always called)

  • Nasty problems depending on what // do something actually does !


For completeness, let's mention a symmetric design approach : Template pattern (base implementation calling specific sub-part)



Suppose I have virtual function foo() in class B, and I need slightly different behavior in one of B's derived classes, class D. Is it OK to create an overriding function D::foo(), and call B::foo() from there, after the special case treatment? Like this:


void D::foo()
{
if (/*something*/)
// do something
else
B::foo();
}

I am not asking whether that would work, I know it will. I want to know, whether it is right in terms of a good OOD.



This is perfectly good. In fact, the canonical way of performing some operations is calling the base class method, then do whatever (or the other way around). I am thinking of operator= here. Constructors usually work that way, too, even if this is a bit disguised in the initialization list.



Yes, it is.



Yes, its totally ok as long as you are not violating the Liskov Substitution Principle.



I have seen GUI frameworks use this to fall back on the base class's default implementation which contained code to signal errors/throw an exception/return a generic value.



It's ok. Syntax you had gave can be also used to temporary turn off polymorphism, i.e. when you call obj->B::foo() method will be chosen from class B regardless if foo() is virtual or not and if obj is instance of B or not (it must be an instance of class extending B though).



Yes it is , that's what your compiler do for you every time it generates a constructor and a destructor: calling the mother's one for instance. I often rely on that"trick" in my own code.



It's fine to call base's implementation, but doing it conditionally moves you apart from constructor semantic, contrary to what have been suggested in other answers.


You may run into fragile base class issue in two ways :



  • By assuming B::foo() provides common behavior for the whole hierarchy (ie, forgetting the method isn't always called)

  • Nasty problems depending on what // do something actually does !


For completeness, let's mention a symmetric design approach : Template pattern (base implementation calling specific sub-part)


0 commentaires:

Enregistrer un commentaire