Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/18: Рейтинг темы: голосов - 18, средняя оценка - 4.78
1 / 1 / 0
Регистрация: 26.07.2012
Сообщений: 133

Что происходит с данными класса-наследника при таком приведении

27.09.2012, 10:03. Показов 3907. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
изучал оф.мануал, рихтера и нейджела. залип вот на каком моменте:
"в С# нет специального синтаксиса для приведения типа объекта к его базовому типу, поскольку такое приведение считается безопасным неявным преобразованием"


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class A
{
  public int a;
  public virtual void  ToStr(){Console.WriteLine("Base "+a);}
  public A(int a){this.a=a;}
}
public class B:A
{
    public int b;
    public override void  ToStr(){Console.WriteLine("Derived "+a+" "+b);}
    public B(int a,int b):base(a){this.b=b;}
}
 
class Entry
{
    public static void  Main()
    {
        A a=new A(5);
        B b = new B(10,10);
        a=b;
 
    }
}
1. Что происходит с данными класса-наследника при таком приведении? Насколько я помню в С происходило усечение класса,т.е. данные уникальных полей наследника терялись. в С# такое приведение является безопасным...т.е. данные сохраняются каким то образом и к ним можно обратиться?
И почему, собственно, обратное приведение не безопасно, тут-то данные точно не потеряются?
понимаю, вопрос туп, но что-то никак не сдвинусь.
Спасибо.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
27.09.2012, 10:03
Ответы с готовыми решениями:

Как вызвать метод дочернего класса при приведении типов?
Привет у меня есть класс (Батя) и парочка дочерних классов в классе Батя есть метод void Verefication, который унаследовали все его...

Почему при восходящем приведении типов вызывается метод класса потомка?
class T1 { public virtual void P() { Console.WriteLine(1); } } class T2 : T1 {

Что происходит с данными записанными в поток от WebClient.OpenWrite()?
Куда передаются данные из потока,при возврате потока методом OpenWrite? Что с ними происходит? class Ama { static void Main() ...

10
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
27.09.2012, 10:23
Ни в С ни в С# не происходит никаких усечений - данные как были в памяти, так там и остаются.
Разница лишь в том, что при обращении через ссылку базового класса эти данные не видно, так как базовый класс о них попросту не знает.

Цитата Сообщение от navab Посмотреть сообщение
почему, собственно, обратное приведение не безопасно
Потому что нужно точно знать к какому именно потомку производится приведение, а родитель - он и есть родитель.
0
1 / 1 / 0
Регистрация: 26.07.2012
Сообщений: 133
27.09.2012, 10:54  [ТС]
в этом случае обратиться к данным можно только через переопределенные методы?
а чем проблема при приведению к потомкам?данные родителя то они в любом случае содержат?
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
27.09.2012, 12:10
Цитата Сообщение от navab Посмотреть сообщение
в этом случае обратиться к данным можно только через переопределенные методы?
Так точно.

Цитата Сообщение от navab Посмотреть сообщение
а чем проблема при приведению к потомкам?
Проблема в том, что нужно точно знать, к какому из потомков происходит приведение, так как потомки могут быть разные. Потому компилятор не берет на себя ответственность определять, какой из потомков подразумевается, и при неявном приведении выдает ошибку.
Пример:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A { }
class B : A { public int x; }
class C : A { public string y; }
 
void Main()
{
   A obj = GetRandomChild();
   B obj1 = obj; // откуда компилятору знать, что вернулся экземпляр класса B?
   С obj2 = obj; // откуда компилятору знать, что вернулся экземпляр класса С?
 
   B obj3 = (B)obj; // Явное приведение - на свой страх и риск. Если вернулся экземпляр класса С, то вылетит исключение в рантайме
   C obj4 = (C)obj; // Явное приведение - на свой страх и риск. Если вернулся экземпляр класса В, то вылетит исключение в рантайме
}
 
// Метод возвращает случайным образом экземпляр класса B или C
A GetRandomChild()
{
   var rand = new Random();
   if (rand.Nex(1) == 0) return new B();
   else return new C();
}
Цитата Сообщение от navab Посмотреть сообщение
данные родителя то они в любом случае содержат?
Да, данные родителя они содержат, но вот родитель данные потомков не содержит, потому неявное преобразование возможно только от потомка к родителю.
1
1 / 1 / 0
Регистрация: 07.09.2012
Сообщений: 46
03.10.2012, 00:39
kolorotur, странно почему компилятор не позволяет определить свой оператор inplisit для приведения к потомку? Можно было бы вставить проверку на is и выкидывать исключение.

Просто синтаксис стал бы намного проще...
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
03.10.2012, 10:21
Цитата Сообщение от Uletchik Посмотреть сообщение
странно почему компилятор не позволяет определить свой оператор inplisit для приведения к потомку?
Почему не позволяет? Еще как позволяет:
C#
1
2
3
4
5
6
7
8
class A
{
   public static implicit operator B(A obj)
   {
      if (obj is B) return (B)obj;
      throw new InvalidOperationException("obj is not B");
   }
}
Только это же идиотизм получается - определять операторы для потомков в базовом классе, т.к. при проектировании базового класса нужно будет знать, сколько и каких потомков у него будет, что невозможно в принципе.

А "простота" синтаксиса с большой вероятностью приведет к очень веселым ночам, проведенным в интимной обстановке с дебаггером.
1
1 / 1 / 0
Регистрация: 07.09.2012
Сообщений: 46
03.10.2012, 11:32
A мне VS 2010 пишет: "Ошибка 3: не разрешено пользовательское преобразование в базовый класс или из базового класса" ????
1
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
03.10.2012, 11:47
Да, действительно - не позволяет. Не знал, спасибо за наводку!

Оберегает, так сказать, от идиотизма
0
1 / 1 / 0
Регистрация: 07.09.2012
Сообщений: 46
03.10.2012, 12:38
Цитата Сообщение от kolorotur Посмотреть сообщение
Да, действительно - не позволяет. Не знал, спасибо за наводку!

Оберегает, так сказать, от идиотизма
Предпочитю чтоб от осмысленного идиотизма не оберегали.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
03.10.2012, 13:46
Мне вот интересно, почему такую штуку нельзя сделать?..
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace ConsoleApplication19
{
    internal class A
    {
        public int X;
 
 
        public A(int x)
        {
            X = x;
        }
    }
 
 
    internal class B : A
    {
        public B(A a) : base(a.X)
        {
 
        }
    }
 
 
    internal class Program
    {
        private static void Main()
        {
            // B b = (B) new A(1); error
            B b = new B(new A(1)); // ok
        }
    }
}
1
1 / 1 / 0
Регистрация: 07.09.2012
Сообщений: 46
03.10.2012, 14:25
Цитата Сообщение от Psilon Посмотреть сообщение
Мне вот интересно, почему такую штуку нельзя сделать?..
....
Была такая мысль, но много полей, даже ссылки копить геморойно и не эстетично и синтаксис опять корявый получается
C#
1
2
3
DeriveDeriveClass A0=new ....
DeriveDeriveClass A1=new ....
DeriveDeriveClass B= new DeriveDeriveClass(A1+A0) // оператор определенный в базовом классе и возвращающий один из более вехних классов
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.10.2012, 14:25
Помогаю со студенческими работами здесь

Правда, что указатель класса-наследника не может указывать на объект класса-родителя?
Доброго времени суток! Пример кода ниже. Правда ли , что указатель класса-наследника не может указывать на объект класса-родителя? ...

Ошибка при вызове метода класса-наследника
помогите не знаю что не правильно сделать выходит что в мемо выводит с класса родителя все нормально методом inform() а вот с наследника...

Что происходит когда передается в функцию базового класса аргумент с типом производного класса?
Есть функция перегруженного оператора"+" в производном классе и в базовом классе который принимает свой тип(базового класса) что...

Лишнее удаление родителя при создании класса наследника
Не могу понять откуда в выводе программы появляется первая надпись "delete A". По идее надписей "delete" должно быть столько же,...

При явном приведении к int получаются числа, но явно не те, что должны быть
Привет. Есть массив unsigned char. В него записываются данные с устройства с помощью библиотеки libusb. Изначально прибор передает...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru