Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.68/72: Рейтинг темы: голосов - 72, средняя оценка - 4.68
Заблокирован
1

Конструкторы базовых классов ("Производный класс не наследует конструкторы базовых классов")

17.03.2012, 13:48. Показов 13050. Ответов 19
Метки нет (Все метки)

Как следует понимать выражение "Производный класс не наследует конструкторы базовых классов", если в конструкторе производного класса всегда через ключевое слово base всегда можно вызвать публичный конструктор базового класса. Что это как не наследование?
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.03.2012, 13:48
Ответы с готовыми решениями:

Рефлексия конструкторы базовых классов
Здравствуйте! Подскажите, пожалуйста, почему метод Type.GetConstructors() не возвращает...

Где посмотреть код базовых классов c#
Доброго времени суток. Подскажите, пожалуйста, как посмотреть код встроенных методов классов,...

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

Построить иерархию классов "Студент", "преподаватель", "персона", "заведующий кафедрой"
Построить иерархию классов: Студент, преподаватель, персона, заведующий кафедрой 1) Разработать...

19
Эксперт .NET
15449 / 11712 / 3076
Регистрация: 17.09.2011
Сообщений: 19,603
17.03.2012, 14:13 2
Если конструктор с определенной сигнатурой не определен в производном классе, то его не получится создать, использовав сигнатуру конструктора из родительского класса.

Простой пример:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Base
{
   public Base() { }
   public Base(string name) { }
}
 
class Derived : Base
{
   public Derived() : base() { }
}
 
void Main()
{
   Derived d = new Derived(); // OK
   d = new Derived("Hello"); // Ошибка при компиляции: в классе Derived не определен конструктор, принимающий на вход строку, хотя у родителя таковой и имеется.
}
0
Заблокирован
17.03.2012, 14:19  [ТС] 3
Да это-то понятно. То же самое, например, верно и для любой другой функции-метода базового класса, а не только его конструктора. Хочется понять, причем здесь наследование?
0
Эксперт .NET
15449 / 11712 / 3076
Регистрация: 17.09.2011
Сообщений: 19,603
17.03.2012, 14:50 4
Цитата Сообщение от thick_int Посмотреть сообщение
То же самое, например, верно и для любой другой функции-метода базового класса, а не только его конструктора.
Простите, ЩИТО?!
Если ваше утверждение верно, то полиморфизм не может существовать в принципе.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Base
{
   public Base() { }
   public Base(string name) { }
 
   public void Foo();
}
 
class Derived : Base
{
   public Derived() : base() { }
}
 
void Main()
{
   Derived d = new Derived(); // OK
   d.Foo(); // ОК, так как метод Foo определен в базовом классе и наследуется в производном.
}
Цитата Сообщение от thick_int Посмотреть сообщение
Хочется понять, причем здесь наследование?
Вот именно при том, что с методами такое проходит, а с конструкторами - нет.
0
Заблокирован
17.03.2012, 15:12  [ТС] 5
Ну при чем здесь полиморфизм, когда речь идет всего лишь о том, как понимать выражение, указанное выше?
Если, все это упростить, то в сухом остатке выйдет лишь то, что
1) При обращении к конструктору производного класса, если не указано иное, вызывается умолчальный конструктор базового класса.
2) Если в базовом классе оный отсутствует, то объект производного класса не создается, а компилятор выдает сообщение об ошибке.

И теперь вопрос, как к этому прикрутить исходный посыл: "Производный класс не наследует конструкторы базовых классов".
0
Эксперт .NET
15449 / 11712 / 3076
Регистрация: 17.09.2011
Сообщений: 19,603
17.03.2012, 15:24 6
Цитата Сообщение от thick_int Посмотреть сообщение
Ну при чем здесь полиморфизм
Ну вы же написали выше, что правило не-наследования конструкторов относится и к методам. А ведь на наследовании методов и основана львиная часть идеи полиморфизма.

Цитата Сообщение от thick_int Посмотреть сообщение
1) При обращении к конструктору производного класса, если не указано иное, вызывается умолчальный конструктор базового класса.
Нет.
При обращении к конструктору производного класса вызывается конструктор производного класса и только конструктор производного класса, если не указано иное. Если он не определен, то выходит сообщение об ошибке, даже если такой конструктор и определен в базовом классе.

Цитата Сообщение от thick_int Посмотреть сообщение
2) Если в базовом классе оный отсутствует, то объект производного класса не создается, а компилятор выдает сообщение об ошибке.
Опять нет.
Если в производном классе оный отсутствует, то объект производного класса не создается, а компилятор выдает сообщение об ошибке.

Цитата Сообщение от thick_int Посмотреть сообщение
как к этому прикрутить исходный посыл: "Производный класс не наследует конструкторы базовых классов".
Вот именно так, как описано выше и показано в первом примере.

Если метод, определенный в базовом классе, можно вызывать по ссылке из производного класса (даже если он в нем не переопределен), то конструктор можно использовать только тот, который определен в конкретном создаваемом классе.

Посмотрите еще раз на пример в моем первом сообщении и комментарии к коду.
0
Заблокирован
17.03.2012, 15:44  [ТС] 7
Да не это я имел в виду, когда говорил о наследовании, а всего лишь о том, что метод базового класса также можно вызвать, например вот так:
C#
1
base.Foo();
То есть, синтаксис чть-чуть другой, но суть то та же, что определно в базовом классе, так или иначе (ну с поправкой на спецификаторы доступа) вызывается из производного класса.


Цитата Сообщение от kolorotur Посмотреть сообщение
Нет.
При обращении к конструктору производного класса вызывается конструктор производного класса и только конструктор производного класса, если не указано иное. Если он не определен, то выходит сообщение об ошибке, даже если такой конструктор и определен в базовом классе.
А вот тут Вы ошибаетесь. Я приведу отрывок из книги Нейгела, "С#4 и платформа .NЕТ 4 для профессионалов" (стр. 148)

Понимая все это, мы можем посмотреть, что именно происходит при создании каждого экземпляра порожденного класса. Предполагая сквозное использование конструкторов по умолчанию, компилятор сначала выбирает конструктор того класса, экземпляр которого он пытается создать, в данном случае — Nevermore60Customer. Первое, что делает конструктор по умолчанию Nevermore6OCustomer — пытается вызвать конструктор по умолчанию своего непосредственного базового класса — GenericCustomer. Затем конструктор GenericCustomer пытается вызвать конструктор своего базового класса — System. Object. Класс System.Object не имеет базового класса, поэтому его конструктор просто выполняется и возвращает управление конструктору GenericCustomer. Этот конструктор выполняется и, прежде чем вернуть управление конструктору Nevermore60Customer, инициализирует name значением null. В свою очередь, конструктор Nevermore60Customer выполняется, инициализируя highCostMinutesUsed нулем, после чего завершается. К этому моменту экземпляр успешно сконструирован и инициализирован.
В результате имеем последовательный вызов конструкторов всех классов иерархии, начиная с System.Object и заканчивая инициализируемым классом. Обратите внимание, что в этом процессе каждый конструктор инициализирует поля собственного класса. Именно так все обычно должно работать, и при добавлении собственных конструкторов вы должны стараться следовать этому принципу.
Обратите внимание на последовательность, в соответствие с которой все происходит. Всегда имеется конструктор базового класса, который вызывается первым. Это значит, что нет проблем для конструктора базового класса вызвать любые методы, свойства и обратиться к любым другим членам базового класса, к которым ему открыт доступ, поскольку базовый класс уже сконструирован и его поля инициализированы. Кроме того, это значит, что если классу-наследнику "не нравится" то, как инициализирован базовый класс, он может изменить начальные значения данных, к которым у него есть доступ. Однако хорошая практика программирования почти наверняка означает, что если вы сможете, то попытаетесь предотвратить возникновение подобных ситуаций и доверите конструктору базового класса иметь дело с его собственными полями.
0
Эксперт .NET
15449 / 11712 / 3076
Регистрация: 17.09.2011
Сообщений: 19,603
17.03.2012, 16:00 8
Цитата Сообщение от thick_int Посмотреть сообщение
Да не это я имел в виду, когда говорил о наследовании, а всего лишь о том, что метод базового класса также можно вызвать[...]
То есть, синтаксис чть-чуть другой, но суть то та же, что определно в базовом классе, так или иначе (ну с поправкой на спецификаторы доступа) вызывается из производного класса.
Так точно, из производного класса можно вызывать как методы, так и конструкторы базового класса.
Но вот использовать конструкторы базового класса для создания производного - нельзя, что я и пытаюсь объяснить.

Цитата Сообщение от thick_int Посмотреть сообщение
А вот тут Вы ошибаетесь.
Да, вы правы - в своем ответе я имел в виду не вызов умолчательного конструктора, а конструктора базового класса с той же сигнатурой.
Умолчательный - конечно же вызывается, если он определен.
1
Заблокирован
17.03.2012, 16:11  [ТС] 9
Все равно спасибо. Суть по моему я понял, а вот к исходному выражению буду относиться просто как к расхожей фразе.
0
Эксперт .NET
15449 / 11712 / 3076
Регистрация: 17.09.2011
Сообщений: 19,603
17.03.2012, 17:02 10
Цитата Сообщение от thick_int Посмотреть сообщение
Все равно спасибо.
Да на здоровье.

Цитата Сообщение от thick_int Посмотреть сообщение
Суть по моему я понял, а вот к исходному выражению буду относиться просто как к расхожей фразе.
Значит не поняли

Смотрите.
Если в базовом классе объявлен некий метод, то его можно вызывать из экземпляра производного класса, даже если он не будет в нем переопределен:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A
{
   public void Foo()
   {
      Console.WriteLine("A: Foo");
   }
}
 
class B : A
{
}
 
void Main()
{
   B b = new B();
 
   // Так можно сделать несмотря на то, что этот метод не определен явным образом в классе B.
   b.Foo(); // Output: A: Foo
}
С конструкторами же такая ерунда не проходит:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A
{
   public A() {}
   public A(int v) {}
}
 
class B : A
{
   public B() { }
}
 
void Main()
{
   B b = new B(42); // Не прокатит, так как конструктор с входящим параметром не определен в классе B и не наследуется, как это было с методом Foo.
}
О чем и пытаются сказать в непонятной вам фразе.
0
Заблокирован
17.03.2012, 17:15  [ТС] 11
И даже в этом случае, объект базового класса A все же будет создан (умолчальным конструктором), а ошибка всплывет только на стадии создания объекта производного класса.
Но все равно, она скорее относится к такому типу, как попытка вызова и любой другой функции, у которой отсутствует соответствующая перегрузка, и не более того.
0
Эксперт .NET
15449 / 11712 / 3076
Регистрация: 17.09.2011
Сообщений: 19,603
17.03.2012, 17:21 12
Цитата Сообщение от thick_int Посмотреть сообщение
И даже в этом случае, объект базового класса A все же будет создан (умолчальным конструктором), а ошибка всплывет только на стадии создания объекта производного класса.
Ошибка всплывет на стадии компиляции. Потому, что в классе B отсутствует нужный конструктор. Не смотря на то, что в классе А он существует. Понимаете?

Цитата Сообщение от thick_int Посмотреть сообщение
Но все равно, она скорее относится к такому типу, как попытка вызова и любой другой функции, у которой отсутствует соответствующая перегрузка, и не более того.
Именно! Компилятор ругается на то, что у класса B отсутствует соответствующая перегрузка конструктора. Почему? Потому что такой конструктор не определен в классе В, то есть его не существует. А в классе "А" он определен. Но класс В с его использованием создать нельзя. Почему? Всё потому же: он существует в классе А, но не в классе В, то есть не наследуется как метод Foo, который можно вызывать из класса B не смотря на то, что он там отсутствует.
0
Заблокирован
17.03.2012, 17:47  [ТС] 13
Цитата Сообщение от kolorotur Посмотреть сообщение
Компилятор ругается на то, что у класса B отсутствует соответствующая перегрузка конструктора
Да наследуется он, просто по-другому вызывается, ну и что толку все равно от этого (базовый класс) конструктора, если его вызов не указан явно. Он что там есть, что нет, пока она не указан, вызывается умолчальный.
А то что компилятор ругается, так он точно также ругается и на всякую другую функцию, имя которой указано неверно. Просто не вижу особого смысла выделять этот случай особо.
0
Эксперт .NET
15449 / 11712 / 3076
Регистрация: 17.09.2011
Сообщений: 19,603
17.03.2012, 18:01 14
Цитата Сообщение от thick_int Посмотреть сообщение
Да наследуется он, просто по-другому вызывается
Каким же образом? Пример?

Цитата Сообщение от thick_int Посмотреть сообщение
А то что компилятор ругается, так он точно также ругается и на всякую другую функцию, имя которой указано неверно. Просто не вижу особого смысла выделять этот случай особо.
В этом вся суть: имя указано не верно.
Именно это делает конструкторы тем самым "особым случаем", о котором говорится в изначальной фразе. И именно поэтому я его в каждом ответе выделяю.

Теперь вопрос: а почему компилятор ругается, что имя указано не верно? В базовом классе ведь есть конструктор с соответствующим параметром, вот он:
C#
1
public A(int value)
Почему я не могу сделать так:
C#
1
var b = new B(42);
?
0
Заблокирован
17.03.2012, 18:20  [ТС] 15
Цитата Сообщение от kolorotur Посмотреть сообщение
Теперь вопрос: а почему компилятор ругается, что имя указано не верно
Потому, что в базовом классе это конструктор носит имя
C#
1
A(int value)
а в наследуемом
C#
1
B(int value)
А Ваша функция Foo(), определенная в базовом классе, как была Foo(), так ей и осталась в производном классе. Всего делов то.
0
Эксперт .NET
15449 / 11712 / 3076
Регистрация: 17.09.2011
Сообщений: 19,603
17.03.2012, 18:34 16
Цитата Сообщение от thick_int Посмотреть сообщение
А Ваша функция Foo(), определенная в базовом классе, как была Foo(), так ей и осталась в производном классе. Всего делов то.
А, вон с какой стороны вы на это смотрите
В общем-то, довольно неплохое объяснение, хоть конструктор и не совсем то же самое что метод.

С таким подходом фраза "Производный класс не наследует конструкторы базовых классов" является просто-напросто очевидной, так как в производном классе просто не реально создать конструктор с именем базового класса, что уже само по себе отрицает наследственность
0
Заблокирован
17.03.2012, 18:44  [ТС] 17
Я вообще косо смотрю на фразу "наследование конструктора", ибо для меня наследование или аналогичное соотношение это прежде всего означает возможность вызова функции через переменную объекта класса.
Но, поскольку через данную перменную нельзя даже вызвать не то что конструктор базового класса, но и конструктор родного класса, то поэтому, мне кажется, что к конструкторам такое понятие как наследование вообще как-то не идет. В этом смысле класс даже не наследует и свой собственный конструктор, но вот использовать их (и родного класса и базового) вполне под силу.
0
2 / 2 / 2
Регистрация: 13.08.2011
Сообщений: 28
28.10.2016, 13:20 18
Ты написал:
При обращении к конструктору производного класса вызывается конструктор производного класса и только конструктор производного класса, если не указано иное. Если он не определен, то выходит сообщение об ошибке, даже если такой конструктор и определен в базовом классе.

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


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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 class A
    {
 
        public A()
        {
            Console.WriteLine("Я конструктор базового класса");
 
        }
    }
 
 
    class B : A
    {
 
    }
 
    //Будет работать и при инициализации B будет выведено   Я конструктор базового класса
 
    class A
    {
 
    }
 
    class B : A
    {
 
    }
 
 
 
 
    class A
    {
        A()
        {
            Console.WriteLine("Я конструктор базового класса");
        }
 
    }
 
    class B : A
    {
 
        B()
        {
            Console.WriteLine("Я конструктор B класса");
        }
 
    }  
 
Тоже будет работать и могу сказать еще больше
 
что даже если определить конструктор без параметров в производном классе B

а у базового A есть констр. по умолчанию, то сначала будет вызван констр. базового класса. и будет выведено
Я конструктор базового класса
а потом сработает конструктор производного класса и будет выведено
Я конструктор класса B - если такое написать в конструкторе производного.
Так что дядя, не парил бы ты мозг людям, если сам ни черта не разбираешься в таких примитивных вещах
0
Эксперт .NET
15449 / 11712 / 3076
Регистрация: 17.09.2011
Сообщений: 19,603
28.10.2016, 16:40 19
xDigitechx, зёма, ты бы прочитал что там дальше в теме написано, а потом хамить начинал.
0
2 / 2 / 2
Регистрация: 13.08.2011
Сообщений: 28
29.10.2016, 16:40 20
Сорян, брат.
Я тогда что-то зол был.
Извини, правда)
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.10.2016, 16:40

Основные понятие классов. Описать класс "Продукция"
1.Описать класс для хранения следующей информации: –название продукции, –стоимость за единицу,...

Основные понятие классов. Описать класс "Продукция"
1.Описать класс для хранения следующей информации: –название продукции, –стоимость за единицу,...

Создать развязочный класс ("многие ко многим") для систематизации объектов классов
Здравствуйте! Есть 2 класса А и В. Они включают в себя некоторый набор полей, свойств и методов....

Класс "Фигура". Реализовать иерархию классов
Класс “Фигура” - абстрактный. В каждом производном классе присутствует - конструктор...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.