Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.69/54: Рейтинг темы: голосов - 54, средняя оценка - 4.69
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3

Перегрузка метода родительского класса

30.05.2021, 08:23. Показов 11090. Ответов 71
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
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
#include <stdio.h>
#include <iostream>
using namespace std;
 
class Device {
    public:
        int serial_number = 12345678;
 
        void turn_on() {
            cout << "Device is on" << endl;
        }
};
 
class Computer: private Device {
    public:
        void turn_on(int i) {
            cout << "Device #" << i << endl;
        }
        
        void say_hello() {
            turn_on();
            cout << "Welcome to Windows 95!" << endl;
        }
};
 
int main() {
    Device Device_instance;
    Computer Computer_instance;
 
    cout << "\t Device" << endl;
    cout << "Serial number is: "<< Device_instance.serial_number << endl;
    Device_instance.turn_on();
 
    // cout << "Serial number is: " << Computer_instance.serial_number << endl;
    // Computer_instance.turn_on();
    // will cause compile time error
 
    cout << "\t Computer" << endl;
    Computer_instance.say_hello();
    return 0;
}
если дать разные имена turn_on то проблема решена. или если через область видимости (или как там по научному это называется) Device:turn_on

но как без всего этого сделать перезагрузку методов ?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
30.05.2021, 08:23
Ответы с готовыми решениями:

Вызов метода родительского класса
Всем доброго вечера! Читаю Р. Лафоре. Он пишет: Т.е. исходя из этого, можно предположить, что производный класс имеет...

Как сделать, чтобы производный класс наследовал все операторы от родительского класса и от родительского родительского
Есть 1й базовый класс в кот. определён operator ++ (); //prefix Есть производный от 1го, 2й класс в кот. дополнительно определён operator...

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

71
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
07.06.2021, 11:19  [ТС]
Студворк — интернет-сервис помощи студентам
...секунду подумаю

Добавлено через 3 часа 42 минуты
Цитата Сообщение от Алексей1153 Посмотреть сообщение
чтото ничего непонял , зачем нам override ? если надо из родител увидеть потомка есть virtual если сразу потомка то делаем объект потомка. + область видимости еще нам в помощь :: и т.д. зачем override при том что это не перегруз а переопределение как virtual

Добавлено через 5 минут
Цитата Сообщение от Алексей1153 Посмотреть сообщение
то using "позволяет из потомка вызывать функции родителя",
а virtual "позволяет из родителя вызывать функции потомка"
подскажите а как нам из родителя 1 увидить метод родителя 2 ?
например
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
#include <stdio.h>
class A{
    public:
    inline void write(unsigned char c){
        putc(c,stdout);
    }
};
class B{
    public:
    virtual void write(unsigned char) = 0;
    void print(const char *c){
        while(*c) write(*c++);
    }
    void print(unsigned long n){
      write(n);
    }
};
class C: public A, public B{
    public:
    using A::write;
    void write (const char *c){
        while(*c) write(*c++);
    }
};
C c;
int main()
{
    c.print(105);
    return 0;
}
в B у нас идёт вызов write(char) который определен в А. как создав объект С сделать так чтоб B понял где искать то что нужно?
вы говорили using инкапсулирует всё в наследника. я указал что B::write(char) virtual... в надежде что using определит эту виртуальную функцию в потомке... но чтото не выходит
0
фрилансер
 Аватар для Алексей1153
6501 / 5732 / 1134
Регистрация: 11.10.2019
Сообщений: 15,350
07.06.2021, 11:42
Цитата Сообщение от alexbmd Посмотреть сообщение
чтото ничего непонял , зачем нам override
пишешь ты, к примеру, класс X и обязательно захотелось, чтобы метод F в нём был виртуальный, причём уже в предке A.
Без указания override не будет такой гарантии (компилятор просто тихо создаст метод в X и всё).
А вот если указать
C++
1
2
3
4
5
6
class X: A
{
   void F() override
   {
   }
};
то компилятор проверит, есть ли в предке виртуальная функция с такой же сигнатурой. Если там её нет, компилятор заругается

Цитата Сообщение от alexbmd Посмотреть сообщение
например
код не компилируется, поскольку в B объявлена чистая виртуальная функция virtual void write(unsigned char) = 0; , а в C она не реализована. Поэтому не удаётся создать экземпляр класса C

using не объявляет виртуальные функции
0
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
07.06.2021, 13:58  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
код не компилируется, поскольку в B объявлена чистая виртуальная функция virtual void write(unsigned char) = 0; , а в C она не реализована. Поэтому не удаётся создать экземпляр класса C
using не объявляет виртуальные функции
да она не реализованна, но класс С получает в наследство всё что имеет класс А - а там она реализована. плюс еще using там добавлен для усиления эфекта
нет , понятно что так неправильно, иначе небылобы этого вопроса... вопрос как из одного родителя всётаки увидеть метод другого родителя ?
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
07.06.2021, 14:30
C++
1
2
3
4
5
6
7
8
Device_instance.turn_on();  // вызвать метод того класса, к которому относится Device_instance
Device_instance.Computer::turn_on(); // принудительно вызвать метод класса Computer 
Device_instance.Device::turn_on(); // принудительно вызвать метод класса Device
 
Device *p_Device_instance = &Device_instance; // указатель базового класса
p_Device_instance->turn_on(); // если turn_on() виртуальная, то вызовется именно та её реализация, которая объявлена для класса, к которому относится Device_instance
// если не виртуальная, то вызов аналогичен  Device_instance.Device::turn_on();
p_Device_instance->Device::turn_on();  // независимо от того, является ли turn_on() виртуальной, принудительно вызовется реализация для класса Device
Добавлено через 6 минут
Цитата Сообщение от alexbmd Посмотреть сообщение
вопрос как из одного родителя всётаки увидеть метод другого родителя ?
Указатель на родителя преобразовать в указатель на наследника и вызвать его метод.

Добавлено через 5 минут
class C: public A, public B{
public:
using A::write;
void write (const char *c){
while(*c) write(*c++);
}
};
C++
1
2
3
4
5
6
7
8
9
10
class C: public A, public B{
    public:
    virtual void write(unsigned char c) override { // если б у класса A write() тоже б была виртуальной, фокус бы не прошёл
                                                     // виртуальная функция переопределяется для B 
        A::write(c);                            // вызов принудительно реализации для класса А
    }
    void write (const char *c){
        while(*c) write(*c++);
    }
};
1
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
07.06.2021, 16:02  [ТС]
TRam_, спасибо за часть с коментариями .. хм...

из всего этого получается (если не прав поправьте)
мы не можем говорить что все методы родителя как бы "копируются" в потомка. иначе не былоб ошибки в моём последнем примере. получается они там и остаются на более низком уровне предка... а просто компилятор если не нашёл метода в потомке спускается на этаж вниз и там ищет и так до подвала. причем без перегрузки методов между этажами.
правильно?
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
07.06.2021, 16:44
Цитата Сообщение от alexbmd Посмотреть сообщение
спускается на этаж вниз
Верно. Можно сказать, что при обычном наследовании объект-наследник содержит в себе все непосредственные объекты-родители, родители содержат своих родителей и т.д., но имена полей/функций (которые будут задействованы для данного объекта) компилятор действительно перебирает сверху вниз (вглубь по иерархии).

Несколько иное поведение в случае виртуального наследования, но это отдельная тема.

Добавлено через 5 минут
Цитата Сообщение от alexbmd Посмотреть сообщение
причем без перегрузки
Да, реализация наследника полностью независима от реализации родителя (хотя ничто не мешает вызвать вторую в первой)
0
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
14.06.2021, 14:38  [ТС]
TRam_, подскажите плиз как исправить этот варнинг
warning: inline function ‘virtual void LLPrint::write(unsigned char)’ used but never defined
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
на ошибки железных регистров RXEN0 TXEN0 и тд плиз не обращяйте внимание (это для avr gcc компилятора)
#include <stdio.h>
#include <stdint.h>
class LLPrint {
 
  public:
    virtual inline void write(unsigned char) =0;
 
    inline void print(char c) {
      write(c);
    }
 
    inline void print(const char *s) {
      while (*s) write(*s++);
    }
 
};
class LLStream : public LLPrint {
 
  public:
    virtual inline unsigned char count() const { }
    virtual inline void write(unsigned char) { }
 
    inline bool available() const {
      return count();
    }
 
    inline void write(const char *s) {
      while (*s) write(*s++);
    }
 
};
#include <assert.h>
class UUART : public LLStream {
  private:
    typedef uint8_t T;
    static const T rx_buffer_size = 16;
    static const T rx_mask = rx_buffer_size - 1;
    T rx_buffer[rx_buffer_size] = {0};
    volatile T rx_head = 0;
    volatile T rx_tail = 0;
    static_assert((rx_buffer_size & rx_mask) == 0, "buffer size must be a power of 2");
    static_assert(rx_buffer_size <= 256, "buffer size must be less than 256");
    const T rxen, txen, rxcie, txcie, udrie;
 
  public:
    UUART(int rxen_= 1, int txen_= 1, int rxcie_= 1, int txcie_= 0, int udrie_= 0)
    : rxen(rxen_), txen(txen_), rxcie(rxcie_), txcie(txcie_), udrie(udrie_)
    {
      assert(rxen_ == 0 || rxen_ == 1);
      assert(txen_ == 0 || txen_ == 1);
      assert(rxcie_== 0 || rxcie_== 1);
      assert(txcie_== 0 || txcie_== 1);
      assert(udrie_== 0 || udrie_== 1);
    }
    inline void begin(const uint32_t ubrr = 9600, const uint8_t format = 6, const bool u2x = 1) {
      // Enable receiver, transmitter, interrupt
      UCSR0B = (rxen << RXEN0) | (txen << TXEN0) | (rxcie << RXCIE0) | (txcie << TXCIE0) | (udrie << UDRIE0);
    }
 
    inline bool irq() {
        rx_buffer[rx_head++ & rx_mask] = UDR0;
        return true;
    }
 
    using LLStream::write; // pull in write(const char *);
    inline void write(uint32_t c){ write((T)c); }
    inline void write(uint16_t c){ write((T)c); }
    inline void write(int32_t c) { write((T)c); }
    inline void write(int16_t c) { write((T)c); }
    inline void write(T c) {
      UDR0 = c;
    }
 
    inline T read() {
      return rx_buffer[rx_tail++ & rx_mask];
    }
 
    inline T peek() {
      return rx_buffer[rx_tail & rx_mask];
    }
 
    inline T count() const {
      return (uint8_t)(rx_head - rx_tail);
    }
 
};
UUART sserial;
 
int main()
{
    sserial.print('c');
    return 0;
}
причём печать работает. но выдаёт варнинг.
0
фрилансер
 Аватар для Алексей1153
6501 / 5732 / 1134
Регистрация: 11.10.2019
Сообщений: 15,350
14.06.2021, 14:48
alexbmd, убери inline у виртуальных функций

да и воообще у всех функций убери

Добавлено через 57 секунд
а переопределяемые виртуальные нужно помечать override

C++
1
2
3
4
class LLStream : public LLPrint
{
  public:
    void write(unsigned char)override { }
0
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
14.06.2021, 15:06  [ТС]
Алексей1153, убрал _только_ у виртуальных, вроде не выдаёт варнинг. спасибо. а почему инлайн помешал виртуал функциям?

то что у остальных inline какие проблеммы ?
0
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,829
14.06.2021, 16:32
alexbmd,
1) inline-функции нужно определение. В случае LLPrint::write определения нет. Об этом вас и предупреждают. Это не ошибка, но очень странный код, на который стоило обратить внимание.

2) inline и virtual вполне сочетаются, но, зачастую, лишь в одном аспекте - правил ODR применяемых к определениям таких функций, что на практике выражается в возможности размещения их в заголовочном файле. Аспект встраивания почти никогда не применяется, потому что в обычной ситуации вызов виртуальной функции выполняется через VTBL, т.е. через указатель, что исключает встраивание по естественным причинам.
2
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
14.06.2021, 23:16
inline void write(uint32_t c){ write((T)c); }
inline void write(uint16_t c){ write((T)c); }
inline void write(int32_t c) { write((T)c); }
inline void write(int16_t c) { write((T)c); }
И что это? Писать только первый байт из 2 или 4 ? Зачем это нужно?
0
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
15.06.2021, 09:31  [ТС]
TRam_, для совместимости похоже

потому что есть например такая функция
C++
1
2
3
4
    inline void print(unsigned long n, int base = DEC) {
      if (base == 0) write(n);
      ...
      }
Добавлено через 4 минуты
а подскажите плиз, структура виртуальной может быть ?

вот если у нас например в классе B есть структура. класс B дочерний от A (схема линковки выше как C>B>A).
если мы в А ссылаемся (если теоретически возможно) на структуру (как тип данных) из класса B
мы можем это как то сделать ?
просто объявляем структуру виртуальной ? virtual struct Data_t; ?
0
фрилансер
 Аватар для Алексей1153
6501 / 5732 / 1134
Регистрация: 11.10.2019
Сообщений: 15,350
15.06.2021, 09:34
alexbmd, виртуальными могут быть только функции-члены
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
15.06.2021, 17:41
Цитата Сообщение от alexbmd Посмотреть сообщение
на структуру (как тип данных) из класса B
Получить определение класса B из класса A конечно можно, но вообще так лучше не делать.

Цитата Сообщение от alexbmd Посмотреть сообщение
а подскажите плиз, структура виртуальной может быть ?
Структура/класс - могут. https://ru.wikipedia.org/wiki/... следование . Но вам это действительно нужно?
0
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
16.06.2021, 12:00  [ТС]
TRam_, спасибо. почитал , решил что могу и обойтись
0
фрилансер
 Аватар для Алексей1153
6501 / 5732 / 1134
Регистрация: 11.10.2019
Сообщений: 15,350
16.06.2021, 12:02
Цитата Сообщение от TRam_ Посмотреть сообщение
Структура/класс - могут
это не делает структуру или класс виртуальными, это всего лишь способ разрешить наследование от двух предков с одной и той же виртуальной функцией, унаследованной ими ещё от более древнего предка
1
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
17.06.2021, 19:29  [ТС]
помогите пожалуйста разобраться с перезагрузкой операторов
https://www.cplusplus.com/doc/tutorial/templates/

1) стр 10. тип (type) это тип возвращаемого объекта функции перезагрузки оператор + ?

2) ну аргумент/параметр тут понятно . но... как действует оператор перезагрузки, в данном случае +. я имею ввиду в стр 24 он (оператор) работает над двумя объектами . а для функции этого оператора на входе только один объект ???

3) в стр 14 мы создаем временный объект , который самоудалиться после ретурна (при выходе из функции оператора)... но не понятно вот что. при создании объекта вызывается и конструктор для него. в даном примере конструктор не инициализирует переменные значит они null. в 15/16 строчке мы в null приплюсуем объект param ... скажем на входе был Bar(1,2)... temp.x = null +1 // равно 1. то есть что было то и осталось. и потом это всё возвращяем в Bar... получается Bar остался с такими же значениями...

вот как это всё работает ?
0
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,829
17.06.2021, 21:13
Цитата Сообщение от alexbmd Посмотреть сообщение
работает над двумя объектами . а для функции этого оператора на входе только один объект
Второй - это this.
Т.е.
a + b - это a.operator+(b), где b - это явный параметр, a - это this.

Добавлено через 4 минуты
Цитата Сообщение от alexbmd Посмотреть сообщение
при создании объекта вызывается и конструктор для него. в даном примере конструктор не инициализирует переменные значит они null. в 15/16 строчке мы в null приплюсуем объект param ... скажем на входе был Bar(1,2)... temp.x = null +1 // равно 1. то есть что было то и осталось. и потом это всё возвращяем в Bar... получается Bar остался с такими же значениями...
Вообще все неправильно.

1) Конструктор и правда ничего не инициализирует, но никаких `null` там нет. Там мусор.
2) в temp.x присваивается значение х текущего объекта плюс значение х из параметра, никаких `null` + 1 нет даже близко!

Добавлено через 4 минуты
Вот этот код
C++
1
2
3
4
5
6
CVector CVector::operator+ (const CVector& param) {
  CVector temp;
  temp.x = x + param.x;
  temp.y = y + param.y;
  return temp;
}
можно переписать так:
C++
1
2
3
4
5
6
CVector CVector::operator+ (const CVector& param) {
  CVector temp;
  temp.x = this->x + param.x;
  temp.y = this->y + param.y;
  return temp;
}
1
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
17.06.2021, 21:18  [ТС]
DrOffset,
хорошо это только два объекта и получается a.operator+(b) а если там a + b + c то что получается ?

и второй вопрос, мучаюсь и не пойму как перезагрузить << чтобы увидеть печать ?
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
#include <stdio.h>
 
class P {
    public:
    virtual void write(unsigned char) = 0;
    inline void print(const char *c) { while (*c) write (*c++); }
    template <class T>
    P& operator<< (const T& i)
    { return print(i); }
};
class W : public P {
    public:
    virtual void write(unsigned char) { }
    inline void write(const char *c) { while (*c) write (*c++); }
};
class S : public W {
    public:
    inline void write(unsigned char  c) { putchar(c); }
    using W::write;
};
S s;
 
#include <stdio.h>
 
int main()
{
    s << "Hello World" << "!";
 
    return 0;
}
0
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,829
17.06.2021, 21:26
Цитата Сообщение от alexbmd Посмотреть сообщение
а если там a + b + c то что получается ?
a.operator+(b).operator+(c)

Цитата Сообщение от alexbmd Посмотреть сообщение
как перезагрузить << чтобы увидеть печать ?
C++
1
2
3
    template <class T>
    P& operator<< (const T& i)
    { print(i); return *this; }
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
17.06.2021, 21:26

При создании объекта наследуемого класса не срабатывает конструктор родительского класса
Уважаемые, эксперты! Суть простая. 1. Есть базовый класс String. В нём массив фиксированной длины, которая задана константой SZ. При...

Почему внук родительского класса не может работать с полями дедовского класса?
Не всё так просто на самом деле. Непонятно, какую роль во всём этом играют шаблоны. Но к делу. Вот код: class base { public: base...

Может ли метод родительского класса обратиться к полю дочернего класса
Может ли метод родительского класса обратиться к полю дочернего класса?

Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса?
Ну то есть так: есть родительский и дочерний класс, в родительском определен виртуальная функция и вызывается в его конструкторе (камень...

Вызов метода класса из метода другого класса
Помогите школнегу Имеется несколько классов class Com { protected: unsigned char bufrd, bufwr; unsigned char tx_index,...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Ноутбук Альфария
kumehtar 24.08.2026
Встретился тут в сети ноутбук Альфария, примарха Альфа-Легиона. Хотя возможно, это ноутбук Омегона, разумеется. Ну как вам?
Мастера простых решений
DevAlt 23.08.2026
В сишарп стэках winforms, да и wpf существует сложная система связывания источниках данных и элементов формы(текстовые поля и метки), опирается все это на технологию событий и мета. . .
Цена ошибки
DevAlt 23.08.2026
Человек я беспокойный и потому заинтересовался OCaml, в чате форсили функторы модулей как суперфичу. Пытаясь отдуплить концепт, наткнулся на тутор с простым примером. А главный принцип обучения от. . .
Сегодня суббота, 22.08.2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины.
zorxor 22.08.2026
Сегодня суббота, 22. 08. 2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины. Кто Я, откуда Я пришел и куда Я иду? Эти вопросы не оставляют меня ни на секунду. Жизнь на планете Земля. . .
Жизня: рисунок укладки багажа, сделанный клодом
anaschu 21.08.2026
Сделал 15 снимков, он по снимкам сделал схему.
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru