Почему этот полиморфный C# кодирует печать, что он делает?

Вот два из моих двух любимых сайтов F#, которые еще не были перечислены:

http://cs.hubfs.net/

http://www.fsharphelp.com

и вот является книгой, которую я нашел полезными (также не ранее перечисленный): Основы F#

http://www.amazon.com/Foundations-F-Experts-Voice-Net/dp/1590597575/ref=pd_bbs_sr_3?ie=UTF8&s=books&qid=1229527045&sr=8-3

68
задан Daniel May 9 October 2009 в 10:31
поделиться

4 ответа

The correct way to think about this is to imagine that every class requires its objects to have a certain number of "slots"; those slots are filled with methods. The question "what method actually gets called?" requires you to figure out two things:

  1. What are the contents of each slot?
  2. Which slot is called?

Let's start by considering the slots. There are two slots. All instances of A are required to have a slot we'll call GetNameSlotA. All instances of C are required to have a slot we'll call GetNameSlotC. That's what the "new" means on the declaration in C -- it means "I want a new slot". Compared to the "override" on the declaration in B, which means "I do not want a new slot, I want to re-use GetNameSlotA".

Of course, C inherits from A, so C must also have a slot GetNameSlotA. Therefore, instances of C have two slots -- GetNameSlotA, and GetNameSlotC. Instances of A or B which are not C have one slot, GetNameSlotA.

Now, what goes into those two slots when you create a new C? There are three methods, which we'll call GetNameA, GetNameB, and GetNameC.

The declaration of A says "put GetNameA in GetNameSlotA". A is a superclass of C, so A's rule applies to C.

The declaration of B says "put GetNameB in GetNameSlotA". B is a superclass of C, so B's rule applies to instances of C. Now we have a conflict between A and B. B is the more derived type, so it wins -- B's rule overrides A's rule. Hence the word "override" in the declaration.

The declaration of C says "put GetNameC in GetNameSlotC".

Therefore, your new C will have two slots. GetNameSlotA will contain GetNameB and GetNameSlotC will contain GetNameC.

We've now determined what methods are in what slots, so we've answered our first question.

Now we have to answer the second question. What slot is called?

Think about it like you're the compiler. You have a variable. All you know about it is that it is of type A. You're asked to resolve a method call on that variable. You look at the slots available on an A, and the only slot you can find that matches is GetNameSlotA. You don't know about GetNameSlotC, because you only have a variable of type A; why would you look for slots that only apply to C?

Therefore this is a call to whatever is in GetNameSlotA. We've already determined that at runtime, GetNameB will be in that slot. Therefore, this is a call to GetNameB.

The key takeaway here is that in C# overload resolution chooses a slot and generates a call to whatever happens to be in that slot.

97
ответ дан 24 November 2019 в 14:15
поделиться

Он должен вернуть «B», потому что B.GetName () содержится в маленьком виртуальном табличном поле для функции A.GetName () . C.GetName () - это «переопределение» времени компиляции, оно не переопределяет виртуальную таблицу, поэтому вы не можете получить ее через указатель на A .

24
ответ дан 24 November 2019 в 14:15
поделиться

Легко, вам нужно только помнить о дереве наследования.

В вашем коде вы храните ссылку на класс типа «A», который создается экземпляром введите "C". Теперь, чтобы определить точный адрес виртуального метода GetName (), компилятор поднимается вверх по иерархии наследования и ищет самое последнее переопределение (обратите внимание, что только «виртуальный» является переопределением, » new '- это нечто совершенно иное ...)

Вот вкратце, что происходит. Ключевое слово new для типа «C» будет играть роль только в том случае, если вы вызовете его для экземпляра типа «C», и тогда компилятор полностью отменит все возможные отношения наследования. Строго говоря, это не имеет ничего общего с полиморфизмом - вы можете видеть это из того факта, что маскируете ли вы виртуальный или невиртуальный метод с помощью ключевого слова 'new', не имеет никакого значения ...

'New' in класс «C» означает именно это: если вы вызываете «GetName ()» для экземпляра этого (точного) типа, то забудьте обо всем и используйте ЭТОТ метод. «Виртуальный», напротив, означает: поднимайтесь по дереву наследования, пока не найдете метод с этим именем, независимо от того, какой именно тип вызывающего экземпляра.

3
ответ дан 24 November 2019 в 14:15
поделиться

Actually, I think it should display C, because new operator just hides all ancestor methods with the same name. So, with methods of A and B hidden, only C remains visible.

http://msdn.microsoft.com/en-us/library/51y09td4%28VS.71%29.aspx#vclrfnew_newmodifier

-1
ответ дан 24 November 2019 в 14:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: