Книга: C# для профессионалов. Том II

Виртуальные и невиртуальные функции

Виртуальные и невиртуальные функции

Виртуальные функции поддерживаются в C# таким же образом, как и в C++. Однако в C# существуют некоторые синтаксические отличия, которые созданы, чтобы исключить возможную неоднозначность в C++. Это означает, что некоторые типы ошибок, которые появляются в C++ только во время выполнения, будут идентифицированы в C# во время компиляции.

Отметим также, что в C# классы всегда доступны по ссылке (что эквивалентно доступу через указатель в C++).

Если в C++ требуется, чтобы функция была виртуальной необходимо просто определить ключевое слово virtual в базовом и производном классах. В противоположность этому в C# необходимо объявить функцию как virtual в базовом классе и как override в версиях производных классов.

class MyBaseClass {
 public virtual void DoSomething(int X) {
  // и т.д.
 }
 // и т.д.
}
class MyClass : MyBaseClass {
 public override void DoSomething(int X) {
  // и т.д.
 }
 // и т.д.
}

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

Если функция не является виртуальной, то можно все равно определить версии этого метода в производном классе, в этом случае говорят, что версия производного класса скрывает версию базового класса, а вызываемый метод зависит только от типа ссылки, используемой для доступа к классу, так же как это зависит от типа указателя, используемого для доступа к классу в C++.

В случае, если в C# версия функции в производном классе скрывает соответствующую функцию в базовом классе, можно явно указать это с помощью ключевого слова new.

class MyBaseClass {
 public void DoSomething(int X) {
  // и т.д.
 }
 // и т.д.
}
class MyClass : MyBaseClass {
 public new void DoSomething(int X) {
  // и т.д.
 } и т.д.
}

Если не пометить новую версию класса явно как new, то код по-прежнему будет компилироваться, но компилятор будет выдавать предупреждение. Предупреждение служит для защиты от любых трудноуловимых ошибок, возникающих во время выполнения. Например, когда написана новая версия базового класса, в которой добавлен метод, имеющий, оказывается, такое же имя, как и существующий метод в производном классе.

В C# можно объявить абстрактную функцию, также как это делается в C++ (в C++ она называются еще чисто виртуальной функцией), но в C# синтаксис будет отличаться: вместо использования =0 в конце определения применяется ключевое слово abstract.

C++:

public:
 virtual void DoSomething(int X) = 0;

C#:

public abstract void Dosomething(int X);

Как и в C++, можно создать экземпляр класса, только если он сам не содержит абстрактных методов и предоставляет реализации всех абстрактных методов, которые были определены в любом из его базовых классов.

Оглавление книги


Генерация: 1.686. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз