C # Inheritance and the Confusion of Virtual Functions

Today I had an interesting problem. I noticed that the following code:

class A { public A() { Print(); } public virtual void Print() { Console.WriteLine("Print in A"); } } class B : A { public B() { Print(); } public override void Print() { Console.WriteLine("Print in B"); } } class Program { static void Main(string[] args) { A a = new B(); } } 

Print

 Print in B Print in B 

I want to know why he prints โ€œPrint in Bโ€ twice.

+6
source share
5 answers

I want to know why he prints โ€œPrint in Bโ€ twice.

You call the virtual method twice on the same object. An object is an instance of B even during constructor A , and therefore an overridden method will be called. (I believe that in C ++ an object only "becomes" an instance of a subclass after the constructor of the base class is executed, as for polymorphism.)

Note that this means that overridden methods called from the constructor will execute before the constructor body of the derived class can execute. This is dangerous. It is for this reason that you should almost never call abstract or virtual methods a constructor.

EDIT: Note that if you do not provide another constructor call for the chain to use : this(...) or : base(...) in the constructor declaration, this is equivalent to using : base() . Therefore, constructor B equivalent to:

 public B() : base() { Print(); } 

For more information on the constructor chain, see my related article .

+11
source

Unlike C ++, where calls to virtual objects in the constructor are limited to definitions within the class itself, overrides are fully respected in C # constructors. The practice is not approved for a good reason ( link ), but it is still allowed: constructor A calls the override provided by B , creating which you see. This is the normal behavior of redundant virtual functions.

+2
source

Because B overrides the Print method. Your variable a is of type B , and the B Print method is as follows:

 public override void Print() { Console.WriteLine("Print in B"); } 
+2
source

If you do not call the base class constructor, the default constructor for the base class will be called implicitly ( MSDN ).

You would not get double output if you defined class A constructors as follows:

 class A { public A() { // does nothing } public A(object a) { Print(); } } 

The reason he prints "Print to B" in both cases is because Print () is overridden in class B, so B.Print () is what is called by both constructors.

I think you can force A.Print () to be called in constructor A as follows:

 class A { public A() { ((A)this).Print(); } } 

Hope this helps.

+2
source

Since you have an instance of B that overrides Print, so the overridden method is called. In addition, Ctor and then B will be launched, so it is printed twice.

+1
source

Source: https://habr.com/ru/post/926526/


All Articles