19 / 19 / 8
Регистрация: 26.01.2014
Сообщений: 56
1

Доступ к приватному методу наследника через родителя

21.02.2014, 09:07. Показов 2981. Ответов 14
Метки нет (Все метки)

Тут натолкнулся на интересную штуку.
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
#include <iostream>
using namespace std;
 
class A {
public:
 
    virtual void f() {
        cout << "A.f" << endl;
    }
};
 
class B : public A {
 
    void f() {
        cout << "B.f" << endl;
    }
};
 
/*
 *
 */
int main(int argc, char** argv) {
    A *a = new B();
    a->f();
    //    B *b = new B();
    //    b->f();
    return 0;
}
есть какие-то доводы в пользу такого поведения?
Или это зависит от реализации? У меня a->f() выдает B.f , а b->f(), как и положено не компилируется.
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.02.2014, 09:07
Ответы с готовыми решениями:

Доступ к приватному члену через нестатическую ссылку
Привет всем. забуксовал.. подтолкните пжалста: ситуация: - в хедере class A { private: int...

Доступ к приватному полю через адрес экземпляра объекта
Объясните такой момент class A { private: char s; public: char Get(){ return s; }

Нужно из класса наследника передать параметры в класс родителя
#include &lt;stdio.h&gt; #include &lt;conio.h&gt; #include &lt;math.h&gt; class ploskost{ protected: float d;...

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

14
Эксперт по математике/физикеЭксперт С++
1989 / 1319 / 379
Регистрация: 16.05.2013
Сообщений: 3,423
Записей в блоге: 6
21.02.2014, 09:15 2
Цитата Сообщение от stikkas Посмотреть сообщение
а b->f(), как и положено не компилируется.
А в какой секции вы объявили f() в классе В?
0
19 / 19 / 8
Регистрация: 26.01.2014
Сообщений: 56
21.02.2014, 09:23  [ТС] 3
а что не заметно?
по-умолчанию у class - private
у struct - public
Этот вопрос возник по аналогии с Java, там запрещено сужать область доступа для переопределяемых методов.
0
Эксперт по математике/физикеЭксперт С++
1989 / 1319 / 379
Регистрация: 16.05.2013
Сообщений: 3,423
Записей в блоге: 6
21.02.2014, 09:27 4
Вот и подумайте об этом.
А в остальном не вижу ни чего удивительного или я просто не понял вашего вопроса...
0
19 / 19 / 8
Регистрация: 26.01.2014
Сообщений: 56
21.02.2014, 09:30  [ТС] 5
Вопрос в том, что получается С++ допускает возможность вызова закрытого метода потомка через указатель на базовый класс.
0
320 / 225 / 74
Регистрация: 22.11.2013
Сообщений: 865
Записей в блоге: 1
21.02.2014, 09:34 6
Цитата Сообщение от stikkas Посмотреть сообщение
Или это зависит от реализации? У меня a->f() выдает B.f , а b->f(), как и положено не компилируется.
Ну правильно класс B наследник класса А, функция-член virtual void f() у него перегружаема и объявлена как public поэтому к ней и можно обратиться из main(). Но при таком обращении ей соответствует void f() класса B. Вот и Ваш ответ (т.е. она видна из класса А, но работает по процедуре класса B). А на прямую к ней не обратишься Вы сами пишите
Цитата Сообщение от stikkas Посмотреть сообщение
по-умолчанию у class - private
Но У Вас обращение к классу A...
0
Эксперт по математике/физикеЭксперт С++
1989 / 1319 / 379
Регистрация: 16.05.2013
Сообщений: 3,423
Записей в блоге: 6
21.02.2014, 09:43 7
Вы вызываете функцию f() посредством указателя на класс А где эта ф-я указана со спецификатором public. Однако так как эта функция виртуальная то вызываемая функция будет искаться по таблице виртуальных функций, а не как обращение к объекту класса В. Т.е. будет просто передан указатель на функцию f() из класса В.
0
Модератор
Эксперт по электронике
8698 / 6496 / 879
Регистрация: 14.02.2011
Сообщений: 22,719
21.02.2014, 09:50 8
Цитата Сообщение от stikkas Посмотреть сообщение
Вопрос в том, что получается С++ допускает возможность вызова закрытого метода потомка через указатель на базовый класс.
да
если посмотришь на дизасемблированый код
то увидишь две таблицы виртуальных функций для класса A и для B
что то типа
Assembler
1
2
;A
offset  f_a;
Assembler
1
2
;B 
offset f_b;
имена я придумал свои, у каждого компилятора свое искажение имен
так в результате
Цитата Сообщение от stikkas Посмотреть сообщение
C++
1
2
A *a = new B();
   a->f();
идет обращение к таблице B
и вызывается f_b
и все в порядке на уровне исполнения
а уровень доступа это на этапе компиляции, в исполняемом коде уже нет ни publiс ни private

Добавлено через 2 минуты
обычно делают наоборот закрытый метод родительского класса открывают в классе наследнике
0
320 / 225 / 74
Регистрация: 22.11.2013
Сообщений: 865
Записей в блоге: 1
21.02.2014, 09:50 9
Ilot,

Не по теме:

солидарность примите :)

0
19 / 19 / 8
Регистрация: 26.01.2014
Сообщений: 56
21.02.2014, 10:06  [ТС] 10
ValeryS,
Это я все прекрасно понимаю. Просто с логической точки зрения запрещенный метод должен быть с любой стороны запрещенным (я так думаю, не берем в расчет доступы по указателям и смещениям);
Вот и все.
А так можно сделать как в Python или Javascript - договориться, что то что начинается с подчеркивания - это закрытый (ну если очень хочется то обратиться и к нему напрямую).
Вопрос заключался в том, может кто знает, как на такую ситуацию смотрят создатели языка. Такое поведение считается нормальным? (не с точки зрения техники выполнения кода, здесь все внорме).
Если да, то вопросов нет.
А если нет, то есть какие-то сложности отслеживания данных ситуаций на стадии компилирования?
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
21.02.2014, 10:17 11
Цитата Сообщение от ValeryS Посмотреть сообщение
обычно делают наоборот закрытый метод родительского класса открывают в классе наследнике
Обычно уровень видимости вообще не меняют. Какой смысл в открытии ранее закрытого метода? Так же не получится воспользоваться радостями полиморфизма (использовать базовый класс, где подразумевается производный). Если уж хочется запретить вызов виртуальной функции из базового класса, сделайте ее чистой (pure virtual).
0
Модератор
Эксперт по электронике
8698 / 6496 / 879
Регистрация: 14.02.2011
Сообщений: 22,719
21.02.2014, 10:45 12
Цитата Сообщение от Tulosba Посмотреть сообщение
Обычно уровень видимости вообще не меняют.
простой пример
MFC класс CFormView метод Create для создания окна
зарыт
я делаю свой производный класс
как я должен создать окно?
переопределить метод и объявить его открытым
ты предлагаешь что то другое?
Цитата Сообщение от Tulosba Посмотреть сообщение
Если уж хочется запретить вызов виртуальной функции из базового класса,
речь идет о уже готовых библиотеках классов
Цитата Сообщение от stikkas Посмотреть сообщение
Просто с логической точки зрения запрещенный метод должен быть с любой стороны запрещенным (я так думаю, не берем в расчет доступы по указателям и смещениям);
компилятор делает код понятный процессору, а на уровне процессора пока нет закрытых функций
Цитата Сообщение от stikkas Посмотреть сообщение
А так можно сделать как в Python или Javascript
эти программы работают на виртуальных машинах, видать в них есть закрытые участки кода
Цитата Сообщение от stikkas Посмотреть сообщение
Вопрос заключался в том, может кто знает, как на такую ситуацию смотрят создатели языка.
раз разрешили значит нормально смотрят, но это мое мнение
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
21.02.2014, 10:53 13
Лучший ответ Сообщение было отмечено stikkas как решение

Решение

Цитата Сообщение от stikkas Посмотреть сообщение
Такое поведение считается нормальным?
Такое поведение чем то сродни привязке параметра по умолчанию во время компиляции для виртуальных функций. Может быть Вы слышали выражение:
C makes it easy to shoot yourself in the foot. C++ makes it harder, but when you do, it blows away your whole leg.
Сейчас правда речь не о сравнении C и C++, а о том, что в этих языках есть тонкие места, с которыми рано или поздно сталкивается любой разработчик. Надо их просто знать. И да, всё, что соответствует стандарту языка, считается нормальным.
C++11 §11.5
The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it.
И приведен практически Ваш пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class B {
public:
   virtual int f();
};
class D : public B {
private:
   int f();
};
void f() {
   D d;
   B* pb = &d;
   D* pd = &d;
   pb->f(); // OK: B::f() is public,
            // D::f() is invoked
   pd->f(); // error: D::f() is private
}
Добавлено через 8 минут
Цитата Сообщение от ValeryS Посмотреть сообщение
речь идет о уже готовых библиотеках классов
Согласен. Но ты же не будешь отрицать, что:
Цитата Сообщение от Tulosba Посмотреть сообщение
Обычно уровень видимости вообще не меняют.
2
19 / 19 / 8
Регистрация: 26.01.2014
Сообщений: 56
21.02.2014, 10:54  [ТС] 14
Цитата Сообщение от Tulosba Посмотреть сообщение
C makes it easy to shoot yourself in the foot. C++ makes it harder, but when you do, it blows away your whole leg.
yeap, it's right
0
Модератор
Эксперт по электронике
8698 / 6496 / 879
Регистрация: 14.02.2011
Сообщений: 22,719
21.02.2014, 11:28 15
Цитата Сообщение от Tulosba Посмотреть сообщение
Но ты же не будешь отрицать, что:
не буду
но ООП в С++ имеет столько дырок
тот же MFC создал какой то свой ООП
и мое выражение
Цитата Сообщение от ValeryS Посмотреть сообщение
обычно делают наоборот
относилось скорей к нему, чем например к Qt
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.02.2014, 11:28
Помогаю со студенческими работами здесь

Как получить доступ к приватному полю
Всем доброго времени суток! Есть такое задание: нужно написать класс, который помимо всего прочего...

Как избежать повтора параметров конструктора класса-родителя в конструкторе наследника?
С каждым новым наследуемом классом, число параметров конструктора увеличивается. class A {...

Указание родительскому методу брать данные конечного Наследника
Есть примерный такой код. Как указать чтобы родительский метод брал данные конечного наследника ?...

Почему извне есть доступ к приватному nested-классу?
class Test { struct PrivateType { PrivateType() {} }; public: void func(PrivateType) {} };...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru