ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.12.2025

Просмотров: 3171

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

c l a s s MyClas s

{

s t a t i c p u b l i c f l o a t

F l o a t T i m e s 2 ( f l o a t f )

{

 

 

 

/ / Все

о т л и ч н о

р а б о т а е т

f l o a t

f R e s u l t

= 2

* f ;

r e t u r n

f R e s u l t ;

 

}

 

 

 

}

Константа 2 имеет тип i n t . i n t , умноженный на f l o a t , дает f l o a t , который вполне может быть сохранен в переменной f R e s u l t типа f l o a t .

Такое же сообщение об ошибке может возникать и при выполнении операций не "неестественными" типами. Например, нельзя сложить две переменные типа char, не С# может при необходимости конвертировать переменную c h a r в значение int.

приводит к следующему: c l a s s M y C l a s s

{

s t a t i c p u b l i c v o i d S o m e F u n c t i o n ( )

{

c h a r c l = ' a ' ; c h a r c 2 = ' b ' ;

// Я не з н а ю , ч т о э т о должно о з н а ч а т ь , но в с е р а в н о это // н е в е р н о — х о т я и не по т о й п р и ч и н е , о к о т о р о й вы / / д у м а е т е

c h a r сЗ = cl + с 2 ;

} }

Сложение двух символов не имеет смысла, но С# все равно попытается это сделать Поскольку сложение для типа c h a r не определено, он преобразует cl и с2 в значение типа i n t и выполнит их сложение (технически c h a r представляет собой интегральный тип). К сожалению, результат этого сложения преобразовать обратно в c h a r не удастся без помощи со стороны программиста (см. главу 3, "Объявление переменных значений").

Большинство (хотя и не все) преобразований без проблем выполняется при их явном указании. Так, следующая функция компилируется без каких-либо нареканий:

c l a s s MyClas s

{

s t a t i c p u b l i c f l o a t F l o a t T i m e s 2 ( f l o a t f )

{

/ / З д е с ь и с п о л ь з о в а н о я в н о е f l o a t f R e s u l t = ( f l o a t ) ( 2 . 0 r e t u r n f R e s u l t ;

пр е о б р а з о в а н и е

*f ) ;

}

}

Результат умножения 2 . 0*f имеет тип d o u b l e , как и ранее, однако программист' явно указал, что он хочет преобразовать полученное значение к типу f l o a t , даже если это приведет к потере информации (см. главу 3, "Объявление переменных-значений").

Второй подход к проблеме может состоять в том, чтобы явно указать необходимы! тип константы:

378

Часть VI.

Великолепные десятки

Г л а в

 

 


class M y C l a s s

{

s t a t i c p u b l i c f l o a t F l o a t T i m e s 2 ( f l o a t f )

{

/ / З д е с ь 2 . OF — к о н с т а н т а т и п а f l o a t f l o a t f R e s u l t = 2 . OF * f;

r e t u r n f R e s u l t ;

}

В этой версии функции использована константа 2.0 типа f l o a t , а не d o u b l e , как принято по умолчанию, f l o a t , умноженный на f l o a t , дает f l o a t .

Данная ошибка указывает на попытку функции обратиться к члену, на обращение к которому она не имеет прав. Например, метод в одном классе может пытаться обра­ титься к закрытому члену другого класса (см. главу 11, "Классы"), как показано в приве­ денном фрагменте исходного текста,

public c l a s s M y C l a s s

{

p u b l i c v o i d S o m e F u n c t i o n ( )

{

Y o u r C l a s s

uc = new Y o u r C l a s s ( ) ;

// M y C l a s s не и м е е т д о с т у п а к з а к р ы т о м у ч л е н у

uc.nPrivateMember = 1;

}

 

}

 

public c l a s s

Y o u r C l a s s

"{

private int nPrivateMember = 0;

}

Обычно такая ошибка не столь очевидна. Зачастую оказывается просто забытым де­ скриптор члена или всего класса, а по умолчанию член класса является закрытым. Так, nPrivateMember остается закрытым в следующем фрагменте исходного текста:

class

M y C l a s s

//

Доступ к

к л а с с у

по умолчанию - i n t e r n a l

(

 

 

 

 

 

 

p u b l i c v o i d S o m e F u n c t i o n ( )

 

{

 

 

 

 

 

 

Y o u r C l a s s

uc

=

new Y o u r C l a s s ( ) ;

// M y C l a s s не и м е е т д о с т у п а к з а к р ы т о м у ч л е н у

uc . n P r i v a t e M e m b e r = 1;

 

 

}

 

 

 

 

 

 

'public

c l a s s

Y o u r C l a s s

 

 

(

 

 

 

 

 

 

int

n P r i v a t e M e m b e r

= 0 ;

/ / Этот

ч л е н - з а к р ы т ы й !

Глава 16. Десять наиболее распространенных ошибок компиляции

379


Кроме того, несмотря на то что функция S o m e F u n c t i o n () объявлена как public к ней нельзя обратиться из классов других модулей, поскольку класс MyClass сам себе является внутренним.

Мораль этой истории — всегда указывайте уровень защиты ваших классов и их чле нов. Кроме того, не объявляйте открытые члены во внутренних классах — это том сбивает с толку.

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

p u b l i c c l a s s M y C l a s s

 

 

 

{

 

 

 

 

 

p u b l i c v o i d S o m e F u n c t i o n ( )

 

 

{

 

 

 

 

 

i n t

n ;

 

 

 

 

//

Все в

п о р я д к е ,

т а к к а к

С# т о л ь к о в о з в р а щ а е т

з н а ч е н и е

//

в п;

в функцию

з н а ч е н и е

э т о й п е р е м е н н о й не

п е р е д а е т с я

S o m e O t h e r F u n c t i o n ( o u t n ) ;

}

p u b l i c v o i d S o m e O t h e r F u n c t i o n ( o u t i n t n )

{

n = 1;

}

В данном случае переменной п в функции S o m e F u n c t i o n () не присваивается ни

какого значения, поскольку это выполняется

в функции SomeOtherFunctiond

Функция S o m e O t h e r F u n c t i o n () игнорирует

значение out-аргумента, как если 6ы|

его не существовало вовсе. (В главе 3, "Объявление переменных-значений", рассказыва ется о переменных, а ключевое слово o u t рассмотрено в главе 7, "Функции функций".)

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

1.Успешно собрали программу.

2.Когда вы запустили программу с помощью команды Debug ^Start without

Debugging, то получили сообщение Нажмите < E n t e r > д л я завершения п р о г р а м м ы . . ., но по какой-то причине не сделали этого (таким образом, вы-

380

Часть VI. Великолепные д е с я т и


полнение программы продолжается), а вы переключились в Visual Studio 2005 и продолжили редактирование файла.

Примечание: если вы запустили программу посредством команды Debug^Start Debugging и забыли ее завершить, то Visual Studio 2005 запросит вас о том, не

следует ли завершить выполнение программы.

3.Вы попытались собрать программу заново, с новыми обновлениями. В этот мо­ мент вы и получаете рассматриваемое сообщение об ошибке в окне Error List.

Выполнимый (. EXE) файл блокируется Windows до тех пор, пока программа не прекратит работу. Visual Studio не в состоянии перезаписать заблокированный старый

.ЕХЕ-файл новой версией без полного завершения программы.

Чтобы исправить ситуацию, переключитесь на ваше активное приложение и заверши­ те его работу. Если это одно из консольных приложений из данной книги, просто нажми­

те клавишу <Enter>. Вы также можете завершить программу из Visual Studio 2005 по­ средством команды меню Debug^Stop Debugging. После того как старое приложение

прекратит работу, соберите приложение заново.

Если вы не можете избавиться от ошибки таким способом, выйдите из Visual Studio 2005 и перегрузите компьютер. Если не сработает и это — ну, тогда не знаю, чем вам можно помочь...

Посредством этого сообщения С# пытается информировать о том, что вы перегру­

 

жаете метод базового класса без его перекрытия (см. детальное описание в главе 13,

 

Полиморфизм"). Давайте рассмотрим следующий пример:

 

public

 

c l a s s

B a s e C l a s s

 

 

I

 

 

 

 

 

 

public

v o i d

F u n c t i o n ()

v

 

public

c l a s s

S u b c l a s s

: B a s e C l a s s

 

 

public

v o i d

F u n c t i o n ( ) / / h e r e ' s

t h e o v e r l o a d

 

{

 

 

 

 

 

 

}

 

 

 

 

 

 

public

c l a s s

M y C l a s s

 

 

 

public

v o i d

T e s t ( )

 

 

 

{

 

 

 

 

 

 

S u b c l a s s sb = new

S u b c l a s s ( ) ;

 

 

s b . F u n c t i o n ( ) ;

 

 

 

}

 

 

 

 

 

 

16.

 

Десять

наиболее

распространенных

ошибок компиляции

381