472,981 Members | 1,262 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,981 software developers and data experts.

Need help to understand virtual functions

153 100+
I am reading a book which says

Even though unboxed value types don't have a type object pointer, you can still call virtual
methods (such as Equals, GetHashCode, or ToString) inherited or overridden by the type. The
reason is because the CLR can just call these methods nonvirtually and System.ValueType
overrides all of these virtual methods and expects the value in the this argument to refer to an
unboxed value type instance. Remember, a value type is implicitly sealed, and therefore, a
value type cannot be used as the base class of another type. This means that it's impossible for
a value type's virtual method to be overridden by a derived type. This also means that the CLR
can call a value type's virtual methods nonvirtually.



However, calling a nonvirtual inherited method (such as GetType or MemberwiseClone)
requires the value type to be boxed because these methods are defined by System.Object,
so the methods expect the this argument to be a pointer that refers to an object on the heap.
In addition, casting an unboxed instance of a value type to one of the type's interfaces requires
the instance to be boxed, because interface variables must always contain a reference to an
object on the heap. The following code
demonstrates:

Expand|Select|Wrap|Line Numbers
  1. using System; 
  2. internal struct Point : IComparable { 
  3. private Int32 m_x, m_y; 
  4. // Constructor to easily initialize the fields 
  5. public Point(Int32 x, Int32 y) { 
  6. m_x = x; 
  7. m_y = y; 
  8. }
  9. // Override ToString method inherited from System.ValueType 
  10. public override String ToString() { 
  11. // Return the point as a string 
  12. return String.Format("({0}, {1})", m_x, m_y); 
  13. }
  14.  
  15. // Implementation of type-safe CompareTo method 
  16. public Int32 CompareTo(Point other) { 
  17. // Use the Pythagorean Theorem to calculate 
  18. // which point is farther from the origin (0, 0) 
  19. return Math.Sign(Math.Sqrt(m_x * m_x + m_y * m_y) 
  20. - Math.Sqrt(other.m_x * other.m_x + other.m_y * other.m_y
  21. }
  22. // Implementation of IComparable's CompareTo method 
  23. public Int32 CompareTo(Object o) { 
  24. if (GetType() != o.GetType()) { 
  25. throw new ArgumentException("o is not a Point"); 
  26. }
  27. // Call type-safe CompareTo method 
  28. return CompareTo((Point) o); 
  29. }
  30. }
  31.  
  32. public static class Program { 
  33. public static void Main() { 
  34. // Create two Point instances on the stack. 
  35. Point p1 = new Point(10, 10); 
  36. Point p2 = new Point(20, 20); 
  37. // p1 does NOT get boxed to call ToString (a virtual method). 
  38. Console.WriteLine(p1.ToString()); // "(10, 10)" 
  39.  
  40. // p1 does NOT get boxed to call CompareTo. 
  41. // p2 does NOT get boxed because CompareTo(Point) is called. 
  42. Console.WriteLine(p1.CompareTo(p2)); // "-1" 
  43. // p1 DOES get boxed, and the reference is placed in c. 
  44. IComparable c = p1; 
  45. Console.WriteLine(c.GetType()); // "Point" 
  46. // p1 does NOT get boxed to call CompareTo. 
  47. // Since CompareTo is not being passed a Point variable, 
  48. // CompareTo(Object) is called which requires a reference to 
  49. // a boxed Point. 
  50. // c does NOT get boxed because it already refers to a boxed Point. 
  51. Console.WriteLine(p1.CompareTo(c)); // "0" 
  52. // c does NOT get boxed because it already refers to a boxed Point. 
  53. // p2 does get boxed because CompareTo(Object) is called. 
  54. Console.WriteLine(c.CompareTo(p2)); // "-1" 
  55.  
  56. // c is unboxed, and fields are copied into p2. 
  57. p2 = (Point) c; 
  58. // Proves that the fields got copied into p2. 
  59. console.WriteLine(p2.ToString()); // "(10, 10)" 
  60. }

This code demonstrates several scenarios related to boxing and unboxing:
Calling ToString In the call to ToString, p1 doesn't have to be boxed. At first, you'd
think that p1 would have to be boxed because ToString is a virtual method that is inher-
ited from the base type, System.ValueType. Normally, to call a virtual method, the CLR
needs to determine the object's type in order to locate the type's method table. Since p1
is an unboxed value type, there's no type object pointer. However, the C# compiler sees
that Point overrides the ToString method, and it emits code that calls ToString directly
(nonvirtually) without having to do any boxing. The compiler knows that polymor-
phism can't come into play here since Point is a value type, and no type can derive from
it to provide another implementation of this virtual method.
Calling GetType In the call to the nonvirtual GetType method, p1 does have to be
boxed. The reason is that the Point type inheritsGetType fromSystem.Object. So to call
GetType, the CLR must use a pointer to a type object, which can be obtained only by
boxing p1.
Calling CompareTo (first time) In the first call to CompareTo, p1 doesn't have to be boxed
because Point implements the CompareTo method, and the compiler can just call it
directly. Note that aPoint variable (p2) is being passed toCompareTo, and therefore, the
compiler calls the overload of CompareTo that accepts a Point parameter. This means
that p2 will be passed by value to CompareTo and no boxing is necessary.
// p DOES get boxed to call GetType (a non-virtual method).
Console.WriteLine(p1.GetType()); // "Point"
// p1 does NOT get boxed to call CompareTo.
// p2 does NOT get boxed because CompareTo(Point) is called.
Console.WriteLine(p1.CompareTo(p2)); // "-1"
// p1 DOES get boxed, and the reference is placed in c.
IComparable c = p1;
Console.WriteLine(c.GetType()); // "Point"
// p1 does NOT get boxed to call CompareTo.
// Since CompareTo is not being passed a Point variable,
// CompareTo(Object) is called which requires a reference to
// a boxed Point.
// c does NOT get boxed because it already refers to a boxed Point.
Console.WriteLine(p1.CompareTo(c)); // "0"
// c does NOT get boxed because it already refers to a boxed Point.
// p2 does get boxed because CompareTo(Object) is called.
Console.WriteLine(c.CompareTo(p2)); // "-1"
// c is unboxed, and fields are copied into p2.
p2 = (Point) c;
// Proves that the fields got copied into p2.
console.WriteLine(p2.ToString()); // "(10, 10)"
}
}Chapter 5: Primitive, Reference, and Value Types 141
Casting to IComparable When casting p1 to a variable (c) that is of an interface type,
p1 must be boxed because interfaces are reference types by definition. So p1 is boxed,
and the pointer to this boxed object is stored in the variable c. The following call to
GetType proves that c does refer to a boxed Point on the heap.
Calling CompareTo (second time) In the second call to CompareTo, p1 doesn't have to be
boxed becausePoint implements theCompareTo method, and the compiler can just call
it directly. Note that an IComparable variable (c) is being passed-toCompareTo, and
therefore, the compiler calls the overload of CompareTo that accepts anObject para-
meter. This means that the argument passed must be a pointer that refers to an object on
the heap. Fortunately, c does refer to a boxed Point, and therefore, that memory address
in c can be passed to CompareTo, and no additional boxing is necessary.
Calling CompareTo (third time) In the third call to CompareTo, c already refers to a boxed
Point object on the heap. Since c is of the IComparable interface type, you can call only
the interface's CompareTo method that requires an Object parameter. This means that
the argument passed must be a pointer that refers to an object on the heap. So p2 is
boxed, and the pointer to this boxed object is passed to CompareTo.
Casting to Point When casting c to a Point, the object on the heap referred to by c is
unboxed, and its fields are copied from the heap to p2, an instance of the Point type
residing on the stack.

PLEASE HELP ME UNDERSTAND IT.

How can a virtual method be called non-virtually ?
Mar 23 '09 #1
0 1760

Sign in to post your reply or Sign up for a free account.

Similar topics

4
by: vijay | last post by:
I have a doubt with size of classed with virtual functions I have declared A,A1,A2 ,B , C, D some classes with no varaibles but a vitual function each, The size of A is as expected 4 bytes with...
5
by: Ryan Faulkner | last post by:
Hi, Im having a few problems with virtual functions (Im using the Visual C++ environment by the way). I have a base class with three virtual functions and a derived class with a single new...
3
by: CoolPint | last post by:
I read that the return type has to be exactly same for a virtual function to be overriden. While testing something, I discovered something I cannot understand. I cannot understand why the code...
8
by: JustSomeGuy | last post by:
I need to write an new class derived from the list class. This class stores data in the list to the disk if an object that is added to the list is over 1K in size. What methods of the std stl...
8
by: Gunnar G | last post by:
Hi. I'm sorry for this somewhat off-topic message, but since this is the best place to find clever C++ programmers with a lot of wisdom. What I need is suggestions for a C++ project that takes...
10
by: mark | last post by:
I have this class: class Selections { OSStatus Init(); protected: CFMutableSetRef selectionObjects; static void CFASelectionsApplier(const void* value, void* ctx); OSType ready; public:...
13
by: Fao | last post by:
Hello, I am having some problems with inheritance. The compiler does not not return any error messages, but when I execute the program, it only allows me to enter the number, but nothing else...
4
by: robinsand | last post by:
My apologies to those of you who are more advanced Visual C++ .NET programmers, but I am working on a project for an MBA course that is condensed into an eight-week schedule, and I need help...
4
by: Neo | last post by:
I have the following code structure- class A { public: virtual void foo_a()=0; }; class B { public: virtual void foo_b()=0; };
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
4
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.