I have three classes, A, B, and C. B and C are derived from A. Both B and C need to implement a method F. The code in B.F() is a subset of C.F().
Is it a good way declare A.F() as a virtual function and define B.F() and C.F()? There would be the same code in 2 methods, which I would like to avoid. What are the other
possibilities?
Define A.F() with the common code and override it in C.F(). While overriding how can the output of A.F() be used in C.F(), so that repeated code can be avoided?
I guess it's not the best thing to do. If you can avoid code rewriting - sure, do it.
It would be better to define F() in A, as you've said, with the common code for both B and C, and then override it in C.F(), using A::F() call in overriden function. I mean, with this you can firstly execute parent method A.F(), and then go with new extra logic. If you're inheriting B from A, you shouldn't then bother about this method in B at all.
Note that from this point of view, the order will be important. If you want parent code execution to be first, then call A::F() before your additional logic. It's on you to decide, what order to choose, though.
EDIT
I will add a link with a good example for you, if you don't know how to call parent method code inside child method. Take a look, and have a nice time.
Related
Sorry for the badly defined title. What I mean:
(Btw I am working on a game engine, and A is the Scene, B are the Game Objects and C are the Components)
I have 3 classes: A, B, C
A contains B, and B contains C.
A and B has a reference to each other.
B and C has a reference to each other.
(A is forward declarated in B's header, and included in B's implementation)
It's like this: A <-> B <-> C
My situation is this:
I want to use A's method from C. (Like telling the main container to add another B, etc)
~I want to make a reusable function which calls a method at the parent object's parent.
For example in C's derived classes I don't have to care how C reaches A, I just call C's Reach-A-and-do-something method.
My question is that which one should I use and why (or is there a better one?):
In C: GetB().GetA().DoSomething()
C's DoSomething() calls B's DoSomething() which calls A's DoSomething.
The first one looks nicer to me, but in C's implementation i only include B's header, where A is only forward declarated. So I can't use A's methods without explicitly including it in C. (Is this a bad practice, or should I just include it?)
The second one has a big overhead. If I want to use A's XY method, I have to create an XY method in B which calls A's XY and I have to create an XY method in C which calls B's XY.
So I don't know how should I reach higher elements in the hierarchy from the lower elements.
What is the best solution for this?
In C: GetB().GetA().DoSomething()
C's DoSomething() calls B's
DoSomething() which calls A's DoSomething.
I think both are wrong because from architectural standpoint such approach creates strong coupling between the classes. Consider using event dispatcher, that implements the Observer pattern for your logic. Let components send events to each other as well as react to them.
I am not sure about how will this work performance-wise in your case, but I strongly advise against premature optimization unless it's evident.
I am currently working on a C++ design where I have this inheritance structure:
A
/ \
B C
Class A does the computations that are common to both classes B and C, and classes B and C are two different ways of initializing A.
I'd like to add some sort of hybrid initialization, i.e. a class D that would use methods from B and C.
However, I'd need to use diamond inheritance to be able to access B::init() and C::init() to set up the attributes of D.
I know I can avoid diamond problems using virtual inheritance, but I get runtime errors that I don't have when I copy manually the methods. Moreover, I have problems when trying to instantiate the classes B and C, and a colleague advised me to never use diamond inheritance in my designs.
Therefore, I'd like to find some kind of "clean" workaround, which I have not been able to do.
I could put all the initialization routines in class A, but for the moment they are separated nicely and I'd like to avoid having one big class where I can't really separate the distinct groups of functions of the classes B and C. EDIT after answer: This is what I chose, using different cpp files to split my "big" class into logical groups of methods.
I could also remove the inheritance links and replace them with friendship, where the methods of B and C are static and work on a pointer of type A*. This way, I could call B::init(A* a) and C::init(A* a) from D::init(A* a). However, I'd have to replace all the uses of _fooAttribute by a->_fooAttribute, which is a bit cumbersome and does not seem right.
What would you recommend ?
If your design calls for diamond inheritance, then that is what you need to do. People treat it as a "must not use" feature of C++, but the truth of the matter is that it is there, it is fully defined (if somewhat complex to understand), and if your problem space calls for it, you should use it.
In particular, I was not able to understand whether this is, indeed, a diamond inheritance. In particular, does it make sense for the A inside B and the A inside C to be the same instance of A? From your question it would appear that it is not. That Both B and C has a certain, different, way it makes sense to initialize A. If that is the case, this is not a diamond inheritance. Just make sure that B and C inherit A in a non-virtual inheritance.
With that said, make sure this is, indeed, what your design calls for. Can you honestly say that B is a A? That C? Can you honestly say that D is both a B and a C? If not, maybe making A a member of B, C or both, or making B or C members of D would make more sense.
If the only reason you are inheriting from A is as a way to extend A's provided methods, then consider simply making those methods a member of A. As stated above, while reducing code duplication is a worthy cause, the design should make sure that inheritance relationship is a is a relationship. Deviating from that is asking for trouble.
Inheritance is an "is a" relationship. If B is an A, then you're good. The same applies to C. From your description, you do not have this relationship. Instead, you have a utility class (A) that does computations. You might want to make this have static methods as it shouldn't need to store any data in itself, if it's truly a utility. There's nothing wrong with passing A an instance of B or C and having it access the properties that it needs using B->fooAttribute. However, you will probably want both B and C to implement a common interface so you don't have to know which one you're looking at.
A class A possesses an instance c of a class C. Another class B has to modify c through C::setBlah(); method.
Is it bad to create an accessor C getC(); in A and then use A.getC().setBlah() ?
Or should I create a method A::setBlah(); that would call C::setBlah(); ? Isn't it annoying if there are several methods like that ?
As with most "is it bad to do X?" questions, the answer is that it depends entirely on a given situation.
Sometimes it might be a really bad idea to have a getC() sort of function because it breaks encapsulation. Other times it might be completely fine because encapsulation of that detail might be irrelevant, and writing a lot of wrapper functions increases the amount of code that you have to write.
Pick whichever makes the most sense for the given situation. In code that I've written, I've taken both approaches.
If you do go the getC() route, do make sure you return a reference; otherwise you'll be modifying a copy which doesn't sound like what you want. Or, you might consider making A::c public so that you don't need a function at all.
A third option to consider would be inheritance from C, which removes the need for getC() or wrapper functions in A.
A Method C getC(); creates a copy of c, so calling A.getC().setBlah() would modify the copy of c, not the c of A.
If C has many similar methods to be called by classes outside A, I would definitely not add these to A. I prefer to keep interfaces as minimal as possible. If these changes are related and are done together, you may add a dedicated single function to A to execute all calls to C at once and logically collect all these changes under an intuitive name.
Such a setup also raises the question: why does B need to touch A's member C? Maybe your design is not quite right - should C be a member of B rather than A?
Should be a newbie question...
I have existing code in an existing class, A, that I want to extend in order to override an existing method, A::f().
So now I want to create class B to override f(), since I don't want to just change A::f() because other code depends on it.
To do this, I need to change A::f() to a virtual method, I believe.
My question is besides allowing a method to be dynamically invoked (to use B's implementation and not A's) are there any other implications to making a method virtual? Am I breaking some kind of good programming practice? Will this affect any other code trying to use A::f()?
Please let me know.
Thanks,
jbu
edit: my question was more along the lines of is there anything wrong with making someone else's method virtual? even though you're not changing someone else's implementation, you're still having to go into someone's existing code and make changes to the declaration.
If you make the function virtual inside of the base class, anything that derives from it will also have it virtual.
Once virtual, if you create an instance of A, then it will still call A::f.
If you create an instance of B and store it in a pointer of type A*. And then you call A*::->f, then it will call B's B::f.
As for side effects, there probably won't be any side effects, other than a slight (unnoticeable) performance loss.
There is a very small side effect as well, there could be a class C that also derives from A, and it may implement C::f, and expect that if A*::->f was called, then it expects A::f to be called. But this is not very common.
But more than likely, if C exists, then it does not implement C::f at all, and in which case everything is fine.
Be careful though, if you are using an already compiled library and you are modifying it's header files, what you are expecting to work probably will not. You will need to recompile the header and source files.
You could consider doing the following to avoid side effects:
Create a type A2 that derives from A and make it's f virtual
Use pointers of type A2 instead of A
Derive B from type A2.
In this way anything that used A will work in the same way guaranteed
Depending on what you need you may also be able to use a has-a relationship instead of a is-a.
There is a small implied performance penalty of a vtable lookup every time a virtual function is called. If it were not virtual, function calls are direct, since the code location is known at compile time. Wheras at runtime, a virtual function address must be referenced from the vtable of the object you're calling upon.
To do this, I need to change A::f() to
a virtual method, I believe.
Nope, you do not need to change it to a virtual method in order to override it. However, if you are using polymorphism you need to, i.e. if you have a lot of different classes deriving from A but stored as pointers to A.
There's also a memory overhead for virtual functions because of the vtable (apart from what spoulson mentioned)
There are other ways of accomplishing your goal. Does it make sense for B to be an A? For example, it makes sense for a Cat to be an Animal, but not for a Cat to be a Dog. Perhaps both A and B should derive from a base class, if they are related.
Is there just common functionality you can factor out? It sounds to me like you'll never be using these classes polymorphically, and just want the functionality. I would suggest you take that common functionality out and then make your two separate classes.
As for cost, if you're using A ad B directly, the compile will by-pass any virtual dispatching and just go straight to the functions calls, as if they were never virtual. If you pass a B into a place expecting `A1 (as a reference or pointer), then it will have to dispatch.
There are 2 performance hits when speaking about virtual methods.
vtable dispatching, its nothing to really worry about
virtual functions are never inlined, this can be much worse than the previous one, function inlining is something that can really speed things in some situations, it can never happen with a virtual function.
How kosher it is to change somebody else's code depends entirely on the local mores and customs. It isn't something we can answer for you.
The next question is whether the class was designed to be inherited from. In many cases, classes are not, and changing them to be useful base classes, without changing other aspects, can be tricky. A non-base class is likely to have everything private except the public functions, so if you need to access more of the internals in B you'll have to make more modifications to A.
If you're going to use class B instead of class A, then you can just override the function without making it virtual. If you're going to create objects of class B and refer to them as pointers to A, then you do need to make f() virtual. You also should make the destructor virtual.
It is good programming practise to use virtual methods where they are deserved. Virtual methods have many implications as to how sensible your C++ Class is.
Without virtual functions you cannot create interfaces in C++. A interface is a class with all undefined virtual functions.
However sometimes using virtual methods is not good. It doesn't always make sense to use a virtual methods to change the functionality of an object, since it implies sub-classing. Often you can just change the functionality using function objects or function pointers.
As mentioned a virtual function creates a table which a running program will reference to check what function to use.
C++ has many gotchas which is why one needs to be very aware of what they want to do and what the best way of doing it is. There aren't as many ways of doing something as it seems when compared to runtime dynamic OO programming languages such as Java or C#. Some ways will be either outright wrong, or will eventually lead to undefined behavior as your code evolves.
Since you have asked a very good question :D, I suggest you buy Scott Myer's Book: Effective C++, and Bjarne Stroustrup's book: The C++ Programming Language. These will teach you the subtleties of OO in C++ particularly when to use what feature.
If thats the first virtual method the class is going to have, you're making it no longer a POD. This can break things, although the chances for that are slim.
POD: http://en.wikipedia.org/wiki/Plain_old_data_structures
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, its totally ok as long as you are not violating the Liskov Substitution Principle.
Yes, it is.
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)