2009-08-21 5 views
9

Как система знает, что использовать, когда используется это ключевое слово?Как система знает, что использовать, когда используется это ключевое слово?

В последнее время мне задали этот вопрос в интервью. Никогда не задумываясь об этом, я ответил, сказав, что система будет знать текущий контекст, в котором поток управления и решить, что объект будет использоваться вместо этого. Интервьюер не выглядел довольным, и он перешел к следующему вопросу.

Может ли кто-нибудь сказать мне, что интервьюер, возможно, хотел спросить и что было бы ответом? (я думаю, что это может интерпретироваться по-разному и, следовательно, сохранить это как wiki, если кто-то не укажет на то, что не ..)

+2

Почему вики на это? – Joseph

+0

«Система» Вы имеете в виду компилятор Java? Компилятор C#? –

+2

@Joseph мы можем вернуть его обратно в не-wiki? – Sandbox

ответ

12

this ключевое слово является указателем на текущий объект. Все нестатические функции-члены класса имеют доступ к этому указателю.

Указатель на текущий объект обычно предоставляется компилятором в нестатической функции-члене, используя регистр, обычно ECX. Поэтому, когда вы пишете this в нестатической функции-члене, компилятор переведет этот вызов на загрузку адреса из ECX.

Проверить этот простой пример:

 
A t; 
t.Test(); 
004114DE lea   ecx,[t] 
004114E1 call  std::operator > (41125Dh) 

Перед вызова функции-члена нестатического Test() компилятор загружает регистр ECX с [T] (адресом переменного т - будет this внутри метода испытаний).

 
004114DE lea   ecx,[t] 

И внутри функции он может использовать ecx для получения адреса для экземпляра текущего объекта.

+2

Как это C#, более простой CIL был бы уместным. – Dykam

+0

спасибо за ответ убийцы. – 0x4f3759df

9

this является скрытым параметром во всех методах объекта и содержит копию указателя экземпляра.

1

Во время выполнения «это» будет разрешено указатель на текущий объект, поэтому «система» сможет вызвать соответствующий метод для этого объекта.

+0

'... «this» будет разрешен указатель на текущий объект. Как он узнает о текущем объекте? – Sandbox

+0

Я полагаю, что стек метода получит дополнительный параметр с адресом объекта, в контексте которого выполняется метод. – 2009-08-21 15:21:59

0

c c Этот указатель является аргументом невидимого указателя для вашего класса.

Таким образом, по существу первым аргументом метода класса является указатель на сам класс. Вы ссылаетесь на него, используя это.

+0

«это» не является ключевым словом в C. –

+0

и не имеет классов C –

+0

да да .. Я имел в виду C++, конечно. ; ^) – Toad

1

Я бы ответил «Это ссылка на экземпляр текущего класса».

Dan

+0

Это не ответ на вопрос. –

2

Рассмотрим этот класс

class A { 
private: 
    int data; 
public: 
    void SetData(int arg) { 
     this->data = arg; 
    } 
} 

и это код, который вызывает SetData():

A objA; 
objA.SetData(1); 

Когда приведенный выше код компилируется, компилятор выдает что-то эквивалентное этому для функции члена:

void SetData(A* this, int arg) { 
    this->data = arg; 
} 

И код вызова преобразуется в примерно так:

A objA; 
SetData(&objA, 1); 

Что это означает, что при компиляции:

  1. Функции-члены преобразуются в простые, глобальные функции.

  2. Экземпляр класса, к которому принадлежат функции-члены, просто передается им в качестве первого аргумента (или, скорее, его адрес передается).

В заключение, то, что вы называете этим указателем в коде, просто заканчивается тем, что является первым аргументом функции. Это то, как «система знает», которые хотят получить доступ через «этот» указатель.

Приведенный выше пример C++. Если вы на мгновение забыли о CLR и JITting, и все, что происходит на C#, концептуально то же самое.

0

Shematicaly компилятор преобразует такой код:

pObject->someMethod(A,B,C) 

В таком коде, если 'SomeMethod' не является виртуальным:

someMethod(pObject,A,B,C) 

Или в такой код, если 'SomeMethod' виртуальна:

(*pObject->vtable[someMethodIndex]) (pObject, A,B,C) 

И везде, где вы помещаете ключевое слово 'this', вместо него используется первый параметр;

Конечно, компилятор может оптимизировать/упростить, удалив первый аргумент и используя некоторый регистр ЦП (обычно esx), чтобы сохранить адрес объекта.

1

Компилятор правильно решает эту ссылку во время компиляции. Если вы хотите узнать более подробную информацию о некоторых из методов, которые они используют, чтобы сделать это, эта книга расскажет вам все, что вам нужно знать:
http://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools
The Dragon Book

0

Мой ответ был бы: «Кто заботится Он знает Если мне когда-нибудь понадобится узнать более подробно, я сделаю это Google ».

Вы, очевидно, знаете, какой эффект от использования «этого» будет, что, безусловно, является важной вещью. Для 99% задач программирования я бы подумал, что детали того, как это разрешено внутренне, являются пустяками.

+1

Это отношение вряд ли принесет вам одобрение интервьюера. –

+0

Ух ты ... ты уверен, что ты на правильном сайте? –

+0

Ну, мой ответ, ЕСЛИ Я НЕ ЗНАЮ, АКТУАЛЬНЫЙ ОТВЕТ был бы выше! –

0

Оператор «Этот» указывает на текущий объект.Пример, в котором наличие «этого» оператора будет делать различие заключается в следующем:

public class MyClass 
{ 
    int value; 
    public void Test(int value) 
    { 
     MessageBox.Show(value); // Will show the parameter to the function 
     MessageBox.Show(this.value); // Will show the field in the object 
    } 
} 

Обратите внимание, что «этот» оператор не изменит то, что виртуальная функция будет вызываться, если он переопределен в дочернем классе

public class MyClass 
{ 
    public virtual void Test() {} 
    public void CallTest() 
    { 
     this.Test(); 
    } 
} 
public class MyClass2 : MyClass 
{ 
    public override void Test() {} 
} 

Если выполнить следующий код

MyClass c = new MyClass2(); 
c.CallTest(); 

еще будет вызывать MyClass2.Test() и не MyClass.Test()

Итак, оператор «this» просто сообщает вам, что вы обращаетесь к чему-то, объявленному на уровне класса.

+0

Что вы подразумеваете под «тем, что« этот »оператор не изменит, какую виртуальную функцию вызывается, если она переопределена в дочернем классе? ... что вы подразумеваете под этим (каламбур не предназначен)? – Sandbox

13

Хотя ответы, указывающие на то, что «эта» ссылка, по существу, передана в качестве магического «скрытого параметра» для вызова, по существу правильны, полная история на самом деле довольно сложна в C#, чем можно было бы подумать Первый взгляд.

Ссылочные типы просты; ссылочный объект проверяется на нуль, а затем концептуально передается как неназванный, непеременный параметр под названием «this». История сложна по типам значений.

Помните, что типы значений по определению передаются по значению, т.е. передаются путем создания копии данных. Отсюда их имя. Но явно изменяемые типы значений, которые являются чистым злом, и их следует избегать, не могут быть переданы по значению как «это», потому что, если вы вызвали мутатор, «это» в методе мутатора будет мутировать копию, а не оригинал!

Поэтому в вызове метода типа значения, в «этом» не значения приемника, это псевдоним переменного, представляющее место хранения приемника. Мы реализуем это, передавая «это» как управляемый адрес приемника, а не значение получателя.

Теперь мы можем поднять еще одну трудность. Что делать, если переменная, сохраняющая измененное значение, является переменной только для чтения? Теперь, что мы делаем? Если вам интересно, читайте мою статью на эту тему и посмотреть, если вы можете правильно ответить на загадку представлены:

http://blogs.msdn.com/ericlippert/archive/2008/05/14/mutating-readonly-structs.aspx

+3

благодарит вас за ваши слова мудрости. О Великий .... Теперь, пожалуйста, идите вперед и реализуйте новые функции langague, которые взорвут наши коллективные умы. – Anthony

+0

Благодарим вас за ответ и отличную ссылку. – Sandbox