2010-07-14 3 views

ответ

16

Объявив метод как virtual, вы указав свое намерение, что метод может быть переопределен в производном классе.

Объявив свой метод, реализующий в override, ваш являются , указав свое намерение, что вы перекрытый метод virtual.

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

+0

Почему бы не отметить его «абстрактное» и принудительное переопределение? –

+1

@George: Потому что вы можете использовать только абстрактный модификатор в абстрактных классах. –

+3

@George Stocker - Потому что вы можете не захотеть пометить весь свой класс абстрактным (классу нужен абстрактный модификатор, чтобы иметь абстрактные методы). –

5

Поскольку это делает код более читаемым:

class Derived : Base 
{ 
    void Foo(); 
} 

В C++, Foo может или не может быть виртуальный метод, мы не можем сказать, глядя на определение. В C# мы знаем, что метод является виртуальным (или нет), потому что есть либо ключевое слово virtual, либо override.

Комментарий Джейсона ниже - лучший ответ.

(отредактированный для ясности)

+1

... и он дает Intellisense возможность помочь нам переопределить метод. Тип «override» и Intellisense всплывает с выбором и даже заполняет всю сигнатуру метода для нас. Как это здорово? – Tergiver

+5

... и, самое главное, это позволяет компилятору рассказать нам, когда мы допустим ошибку (например, если вы добавите параметр в метод базового класса в C++, он разбивает все производные классы, но вы не можете его узнать - причина некоторых очень неприятных для отслеживания ошибок, потому что бит поведения производного класса просто перестает работать. В C# он дает ошибку для каждого переопределения, которое больше не отменяет ничего) –

+0

_ «В C++ это может быть, t скажем, посмотрев определение ». - Посмотрев определение, мы можем сказать, что это вовсе не C++. – stakx

11

Если вы не добавили ключевое слово override, метод будет скрыт (как если бы у него было ключевое слово new), а не переопределено.

Например:

class Base { 
    public virtual void T() { Console.WriteLine("Base"); } 
} 
class Derived : Base { 
    public void T() { Console.WriteLine("Derived"); } 
} 

Base d = new Derived(); 
d.T(); 

Этот код печатает Base. Если вы добавите override в адрес Derived, код будет распечатать Derived.

Вы не можете сделать это на C++ с помощью виртуального метода. (There is no way to hide a C++ virtual method without overriding it))

+0

Почему так много людей не знают о поведении 'new' по умолчанию ... – Dykam

+1

Я согласен, что это не должно быть законным и должно вызывать ошибку вместо предупреждения. (Изменить: кто-то удалил свой комментарий выше этого). – Dykam

+0

Warings как ошибки FTW! –

1

Не все виртуальные методы должны быть переопределены, хотя все абстрактные методы должны (и должны) быть. Что касается того, почему ключевое слово override является явным, это потому, что переопределение и скрытие ведут себя по-разному. Метод скрытия не вызывается через ссылку на базовый класс, тогда как переопределенный метод. Вот почему компилятор специально предупреждает о том, как вы должны использовать ключевое слово «новое» в случае, когда вы скрываете, а не переопределяете.

10

Это потому, что члены команды C# - все опытные программисты на С ++. И знаете, как зарождается эта конкретная ошибка:

class Base { 
protected: 
    virtual void Mumble(int arg) {} 
}; 

class Derived : public Base { 
protected: 
    // Override base class method 
    void Mumble(long arg) {} 
}; 

Это гораздо более распространено, чем вы могли подумать. Производный класс всегда объявляется в другом файле исходного кода. Обычно вы не ошибаетесь сразу, это происходит, когда вы рефакторинг. Никакой взгляд из компилятора, код работает довольно нормально, просто не делает того, что вы ожидаете от него. Вы можете смотреть на него в течение часа или дня и не видеть ошибку.

Этого никогда не может быть в программе на C#. Даже управляемый C++ применял этот синтаксис, преднамеренно ломаясь с собственным синтаксисом C++. Всегда смелый выбор. IntelliSense снимает лишние формулировки.

В C# есть много синтаксических твинов, которые напоминают синтаксис такого типа.


EDIT: а остальная часть C++ сообщества согласился и принял переопределения ключевое слово в новой C++ 11 спецификации языка.

+1

+1 Лучший ответ IMO, потому что он объясняет «почему» позади решения для дизайна языка, а не «как работают виртуальные вызовы», поскольку более высокие ответы отвечают ... PS. @Hans Я, кажется, натыкаюсь на множество уместных ответов, написанных вами в эти дни :) –

0

Нет необходимости явно переопределять виртуальный метод в производном классе. Маркировка метода virtual только позволяет переопределить.

Смежные вопросы