![]() |
|
![]() | ||
|
Subject:
Overloading Virtual Functions
Category: Computers > Programming Asked by: fritzfinn-ga List Price: $2.00 |
Posted:
26 Jul 2004 11:55 PDT
Expires: 25 Aug 2004 11:55 PDT Question ID: 379269 |
Why can't Virtual Functions be overloaded? What is the correct way to construct a class when a case arises that seems to lend itself to overloading Virtual Functions? Is there an example of this behavior in Design Patterns book by Erich Gamma? |
![]() | ||
|
There is no answer at this time. |
![]() | ||
|
Subject:
Re: Overloading Virtual Functions
From: mikejv-ga on 26 Jul 2004 14:05 PDT |
For C++: Do you read comp.lang.c++.moderated? Perhaps this will help: http://tinyurl.com/4ad3z |
Subject:
Re: Overloading Virtual Functions
From: fritzfinn-ga on 27 Jul 2004 11:37 PDT |
Not too much. I'm not big on using e-mail or online forums for assistance on complex issues. I'd rather hire a consultant, get on the phone, and cut to the chase. In fact I tried to hire Scott Meyers, who wrote Effective C++, and he sent me to the same place. Then I tried the guy who wrote C++ FAQ and his fees were unreasonable at $400 per hour. Anyhow, I did try, but just don't like it, at all. It's a waste of time. On a simple questions yes, but I don't have time to monitor this thing all the time and go back and forth, and back and forth. I wear about 10 different hats. I need verbal information, pronto. My posting this question on Google is basically an experiment. I want to see just how good a responses I can get. I hope my response was not offensive. Thanks for your suggestion. |
Subject:
Re: Overloading Virtual Functions
From: fritzfinn-ga on 27 Jul 2004 11:46 PDT |
Actually, I didn't see the link you provided before I posted last response. Let me take a look and I'll get back to you. Thanks |
Subject:
Re: Overloading Virtual Functions
From: nsinr8r-ga on 31 Jul 2004 08:50 PDT |
You *can* overload virtual functions, but it's not a recommended practice. I tried it out with both GCC and MSVC++ 2003, and neither gave me an error or warning (except for the warning I'll show after the code below). The best sources to read for why this is a bad idea (and what to do instead) both come from the same author: Stephen Dewhurst. Check out his book, C++ Gotchas, which the code I show essentially comes from). The other is his website www.semantics.org, specifically his paper http://www.semantics.org/talknotes/SD2002W_HIERARCHY.pdf, starting on page 10. I gotta say I learned a lot from that book. The code in the book is simpler; I threw in a little more. First suppose you have two classes, Base and Derived, defined as: #include <iostream> using std::cout; class Base { public: virtual void foo(int f) { cout << f; } virtual void foo(double f) { cout << f; } }; class Derived : public Base { public: void foo(int f) { cout << f; } }; int main() { Derived *d = new Derived; Base *b = d; cout << "Calling Base foo(double) through Base\n"; b->foo(3.14); cout << "Calling Base foo(double) through Derived\n"; d->foo(3.14); delete b; } The interesting thing here is that in the second case, when we're trying to call the double version of foo() from the Derived instance, we actually get the int version of foo(). What happened? Essentially, the override of foo() in Derived hid all of the overloaded foo() functions in Base. Dewhurst mentions two solutions in the book: 1) You could make sure that you have overloaded versions of the virtual functions in all your derived classes. This is pretty inflexible, because anyone deriving from any of your classes will have to know about all of the different overloaded versions and write overloaded versions in their derived classes. If they aren't aware of them (and are only aware that foo() exists, they'll run into the same problem: hidden member functions. 2) As he offers in the PDF, you can overload some non-virtual member functions in the base class, then have a set of virtual functions (with different names--not overloaded) that the overloaded non-virtual functions call. The following comes from his PDF (I called the functions foo() to match the code above): class Base { public: void foo(double); // overloaded, non-virtual void foo(int); // protected: virtual void f_double(double); // virtual, not overloaded virtual void f_int(int); // }; inline void foo(int i) { f_int(i); } inline void foo(double d) { f_double(d); } Maybe a little hairier conceptually, but definitely safer. Check out both sources! ------M |
Subject:
Re: Overloading Virtual Functions
From: nsinr8r-ga on 31 Jul 2004 08:53 PDT |
Sorry; I forgot to mention that the only warning I got (at least from MSVC++) was that there would be a conversion from double to int, and that there would be "a possible loss of data," which there was. I had requested 3.14 be printed to the screen, but it instead truncated the number to an integer before printing. |
Subject:
Re: Overloading Virtual Functions
From: fritzfinn-ga on 01 Aug 2004 13:57 PDT |
Thanks very much for responding. Let me provide a better example. Here are the classes: CPortfolioBase which is abstract, i.e. it's never initialized alone. So, the implimentation is done in each derived class. CPortfolioCommodities derived from Base CPortfolioStocks derived from Base Let's say I have a function GetMarketWeight which retrieves a number that weights a markets contribution to total profit. For various reasons, in Commodity portfolio you need to know whether your long or short, plus an index representing day. So, two arguments. In Stock portfolio you only need to pass in day, not Long or Short. So, in each case I'd like to call "GetMarketWeight" from the Base class, Commodity ::GetMarketWeight(LongOrShort, DayIndex) and Stock::GetMarketWeight(DayIndex), but because you can't overload, you have to setup both with two args. So this is what I'd like to do: class CPortfolioBase { public: virtual float GetMarketWeight(short x, long y) = 0; virtual float GetMarketWeight(long y) = 0; }; class CPortfolioCommodities : public CPortfolioBase { public: float GetMarketWeight(short x, long y); } class CPortfolioStocks : public CPortfolioBase { public: float GetMarketWeight(long y); } main() { CPortfolioBase *b; CPortfolioCommodities c; CPortfolioStocks s; float x; x = c.GetMarketWeight(1,1500); x = s.GetMarketWeight(1500); b = &c; x = b->GetMarketWeight(1,1500); b = &s; x = b->GetMarketWeight(1500); } So, regarding both mikejv-ga and nsinr8r-ga suggestions: My problem relates to overloading a pure virtual function. Not overriding. I briefly looked at C++ Gotchas. But don't have the book. I'll order it. This is the problem I run into fairly often. There must be a "correct" solution according to the C++ community for this issue. Hopefully, this is a more concrete example of my problem. Thanks again. |
Subject:
Re: Overloading Virtual Functions
From: tractorguy-ga on 13 Aug 2004 12:55 PDT |
#1: C++ requires an implementation of every pure virtual signature, so that is why your code won't compile. That's just the way C++ is. The interesting question is why? Bland answer: Technically, every function signature needs to have a function associated with it. Your two base classes are each missing one. Result: compile error on any instantiation of a subclass. More interesting is the case where the virtual functions are defined in the base class (which is what to do about it). C++ relates functions with the same names and different numbers of arguments primarily to support the presence of default values for those arguments. Consider the following code: #include <iostream.h> class V { public: virtual int X(int a) {throw "Error in declaration of X(int) - subclass does not define method";} virtual int X(int a, int b) {throw "Error in use of X(int,int) - subclass does not define method";} V() {} virtual ~V() {} }; class W : public V { public: int X(int a) {return a+1;} W() {} ~W() {} }; class Z : public V { public: int X(int a, int b=-1) {return -9;} Z() {} ~Z() {} }; int main( int, char** ) { Z z; V& v=(V&)z; try { cerr << z.X(1,2) << endl; cerr << z.X(1) << endl; cerr << v.X(1,2) << endl; cerr << v.X(1) << endl; } catch ( const char* estr ) { cerr << "Exception:: " << estr << endl; } } It compiles and outputs : -9 -9 -9 Exception:: Error in declaration of X(int) - subclass does not define method Without the default value in the declaration of X in class Z, we get a compile error (method not defined for z.X(1)). So, I believe this was an attempt by C++ designers to somewhat support default values and the autocasting of argument types at compile time in the least confusing way. C++ made the (reasonable) decision that if a function call was ambiguous, it was a compile error. But with default values for some of a function's arguments, many functions could become ambiguous in the presence of inheritance if all ancestor methods are available as candidate instantiations. This would make default values unusable. So the designers simply said "if a subclass is going to define a method, it will have to define *all methods that will be used by variables of its type*". This is reasonable, since it would in any case be confusing if you define a function in a subclass and end up with a parent's instantiation in use due to some weird unforseen autocasting and default value filling. Note that in my code above, it compiles and allows you to use Z.X(a,b) and W.X(a) without defining Z.X(a) or W.X(a,b) *provided you don't refer to W.X(a,b) or Z.X(a) in your code*. That's my $0.02. |
If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you. |
Search Google Answers for |
Google Home - Answers FAQ - Terms of Service - Privacy Policy |