Virtualization in Super Class Constructor

I thought that virtualization did not work in the superclass constructor according to the design of OOP. For example, consider the following C # code.

using System; namespace Problem { public class BaseClass { public BaseClass() { Console.WriteLine("Hello, World!"); this.PrintRandom(); } public virtual void PrintRandom() { Console.WriteLine("0"); } } public class Descendent : BaseClass { private Random randomValue; public Descendent() { Console.WriteLine("Bonjour, Monde!"); randomValue = new Random(); } public override void PrintRandom() { Console.WriteLine(randomValue.NextDouble().ToString()); } public static void Main() { Descendent obj = new Descendent(); obj.PrintRandom(); Console.ReadLine(); } } } 

This code breaks because when the Descendent object is created, it calls the constructor of the base class, and we call the virtual method in the constructor of the base class, which in turn calls the Derived class method and, therefore, it is reset, because randomValue is not initialized to that time.

Similar code works in C ++ because the PrintRandom call is not redirected to a derived class with IMO, the order in C ++ is something like:


1. call the base class constructor
2. Update V - Table for this class
3. calling the constructor code

My question is, firstly, do I correctly agree that, in accordance with the principles of OOP, virtualization should not / should not work in the constructor of a superclass, and secondly, if I am right, why is the behavior different in all languages. NET (I tested it with C #, VB.NET and MC ++)

+4
c ++ c # oop
source share
3 answers

In the original C ++ program, it works as expected: you get a call to the base version of the virtual function in the base class constructor. When calling the constructor, there is only the base class and its virtual functions, so you get the version of the lowest level of the virtual function defined at that time. This does not mean that virtualization cannot be used, you simply will not get subclasses of the versions of virtual methods in the constructors of the base classes (therefore, it is not recommended).

Obviously, as you can see, managed code works differently because (iirc) the entire object is built before the constructors are called, and so you get a virtual subclass function before the subclass constructor. This is a documented difference between the behavior of languages, but must be consistent in .NET languages ​​(since they are all compiled with the same IL).

+4
source share

This does not apply to the principles of OO, in my opinion, up to the platform in question, how it deals with this particular mystery. Calling the virtual method from the constructor is discouraged for this reason, however, if you are going to do this, you need to clearly indicate that you are going to call it, so that any class that overrides it knows what to expect.

Java uses the same approach as .NET, except that in C #, instance variable initializers are executed before the base constructor is called. This means that in your specific example, you can fix the code by initializing random at the declaration point. In Java, this does not help.

As for why MC ++ does not work this way, I don’t know - I suggest you compare the generated IL. I assume that it explicitly calls a non-virtual method call.

EDIT: I suspect I misunderstood the question: how does MC ++ work? If it works the way C # works, this is a good IMO thing, providing a consistent view on the .NET platform.

+3
source share

I would suggest using FxCop for your code. I worked with many people who reject objects raised by this tool as insignificant, but if your code contains many small problems (for example, yours), then the chances of being bitten by one or more of them are much higher.

ReSharper code analysis will also raise this particular problem.

0
source share

All Articles