![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Expert Programmer
|
Virtual global functions
I am reading OOP C++ and am somewhat confused about overloading global functions.
For example, the following operator function is declared in BaseClass.h: std::ostream& operator << (std::ostream& os, const BaseClass& bc);If I understand correctly, this operator cannot be overloaded in DerivedClass because it is not part of the class definition. So is the only way to achieve polymorphic behavior to call a virtual function of BaseClass within the definition of the operator << function? Also, the book states that global automatic type conversions global functions if they are friends of a class. Why? Also, should the function above be a friend of BaseClass? |
|
|
|
|
|
#2 | |||
|
Programming Guru
![]() Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,223
Rep Power: 5
![]() |
Re: Virtual global functions
Quote:
operator<<() function like the above are never part of a class definition anyway.It is possible to declare and define a std::ostream& operator << (std::ostream& os, const DerivedClass& dc);. The issue, however, is in code that only receives a const reference to a BaseClass: the function with BaseClass as second argument will always be called, as the compiler has no way to know that reference actually corresponds to a DerivedClass.Quote:
std::ostream& operator << (std::ostream& os, const BaseClass& bc); function to give different behaviour depending on the actual type of object passed, then yes.Quote:
There is no requirement that an std::ostream &operator<<(std::ostream &, const BaseClass &) function be a friend of BaseClass, unless the definition (ie implementation) of that function needs to access private or protected members of BaseClass. |
|||
|
|
|
|
|
#3 |
|
Expert Programmer
|
Re: Virtual global functions
Thanks, grumpy. It seems very non-OOP that you can't reasonably overload global operator functions, although I suppose it doesn't matter if you are just calling a virtual function in the implementation.
According to my book: "When declaring a global friend function, an automatic type conversion is therefore possible for both the first and second paramenters." The example it gives is as follows: class BaseClass {
friend bool operator < (const BaseClass&, const BaseClass&);
}In the following code, assume BaseClass has a 1-parameter non-explicit constructor that takes an int value: int main() {
BaseClass bc;
if (bc < 1000) ... // OK
if (1000 < bc) ... // OK because operator < is a friend function
}Why is this? As I understand it, a friend of a class just has access to its private members. Is the friend declaration a hint to the compiler? If so, is the friend declaration really necessary or could the function prototype just be declared within the class (which is to say, could the keyword "friend" be removed from the code above). Thanks for helping to clear this up. Last edited by titaniumdecoy; Jun 28th, 2008 at 1:36 PM. |
|
|
|
|
|
#4 | ||
|
Programming Guru
![]() Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,223
Rep Power: 5
![]() |
Re: Virtual global functions
Quote:
Firstly, there is nothing sacrosanct about "OOP" that requires everything to be an object, or that everything involving objects has to be done in a particular manner. Second, even if there was, C++ is a multi-paradigm language and has some features that are unrelated to any object oriented paradigm. Function overloading is one of those features. Overloading is a language feature that has nothing to do with objects. It just means it is possible to create multiple functions that have the same name but different argument lists. For example; std::ostream &operator<<(std::ostream &s, const BaseClass &b); std::ostream &operator<<(std::ostream &s, const DerivedClass &d); The issue that (I suspect) is confusing you is that, when calling functions, it is necessary to match the supplied arguments to the argument list of some actual function that is visible to the compiler. So s << o; will call an operator<< function that depends on the types of s (eg std::ostream) and o as determined at compile time. Let's look at two functions;void DoBase(const BaseClass &b)
{
std::cout << b; // will call the first version above as static type of b is BaseClass
}
void DoDerived(const DerivedClass &b)
{
std::cout << b; // will call the second version above
}
int main()
{
DerivedClass x;
DoDerived(x);
DoBase(x); // x is implicitly converted to BaseClass here
}Virtual function dispatch (ie polymorphic behaviour) is a completely different thing. It is resolved at run time for the code o->SomeVirtualFunction(); so a version of SomeVirtualFunction() that depends on the actual (runtime) type of o is called.Quote:
The basic idea with overloading is that the compiler determines what function is called by matching types at the call point with arguments of candidate functions that can be called. The compiler looks for an exact match first. So; int main()
{
BaseClass a, b; // assume BaseClass is as per your text above
// set values of a and b to something meaningful
if (a < b) Whatever();
}a< b can be changed into a function call. It finds the operator<() you declared above. Assuming it finds no other candidate functions it can call, this is the function that is called.What do I mean in my references to "candidate functions" above? When converting expressions into calls of particular functions, the C++ standard requires the compiler to build a list of candidate functions, and then (if there is more than one candidate) to pick the best one. Consider what would happen if your class also supplied a member function of the form bool operator<(const BaseClass &);. This function (if it exists) is also a valid match. This is why, if you supply both the global function bool operator<(const Baseclass &, const BaseClass &) and the member function version, that compilers will complain about ambiguity: there is more than one "equally best" candidate functions that can be called.OK, having talked about the notion of candidate functions, let's get back to topic and change the example to; int main()
{
BaseClass b; // assume BaseClass is as per your text above
int a;
// set values of a and b to something meaningful
if (a < b) Whatever();
}a<b into a call of an operator function. a is of type BaseClass, so possible matches include any operator<() functions associated with BaseClass. So it finds the function bool operator<(const BaseClass &, const BaseClass &) function. But this isn't a precise match, as a is of type int. So the compiler then attempts to convert the value a to a BaseClass i.e. it looks for a conversion operation. It finds one. So the expression a<b constructs a temporary BaseClass from a, and then calls the operator<() function .... which is now a perfect match.There are a number of other rules that come into play as well. For example, the compiler won't attempt multiple conversions (eg it won't convert a to an X and then convert that X to a BaseClass, even if conversion operators exist so int can be converted to X and X can be converted to BaseClass). This type of conversion is also not allowed on the left hand operand (ie a) to allow finding a match for a member function version of the operator function.As I said in my previous post: the friend keyword has no part in any of this. The global operator<(const BaseClass &, const BaseClass &) function only needs to be a friend of BaseClass if its definition (i.e. implementation) requires access to private or protected members of BaseClass. |
||
|
|
|
|
|
#5 |
|
Expert Programmer
|
Re: Virtual global functions
Thanks again, Grumpy. I appreciate your detailed responses to my questions. I think I have a much better understanding of these ideas now.
|
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Opposite of global in functions | davil | PHP | 7 | Dec 19th, 2007 4:40 AM |
| What is the point of pure virtual functions? | aznluvsmc | C++ | 12 | Apr 14th, 2006 6:48 PM |
| Exporting Functions | victorsk | Visual Basic | 1 | May 18th, 2005 2:32 PM |
| User-defined creatNode and deleteNode functions for a doubly-linked list | jgs | C | 2 | Apr 28th, 2005 8:53 AM |
| Virtual functions on casted objects | Rei | C++ | 1 | Apr 10th, 2005 7:44 AM |