Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.80
kravam
быдлокодер
1691 / 878 / 44
Регистрация: 04.06.2008
Сообщений: 5,423
#1

базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! - C++

12.06.2011, 22:52. Просмотров 1251. Ответов 9
Метки нет (Все метки)

Друзья! Вот код

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
#include <stdio.h>
template <class T>
class otets {
 protected:
  int peremennaya;
};
 
template <class T>
class sinn: public otets<T> {
 void  f ();  
};
 
template <class T>
void sinn<T>::f () {
 otets<T>::peremennaya= 11;
 sinn<T>::peremennaya= 11;
 //peremennaya= 11;
}
 
int main() {
 sinn<int> h;
 printf ("%x\n", &h.otets<int>::peremennaya);
 printf ("%x\n", &h.sinn<int>::peremennaya);
 printf ("%x\n", &h.peremennaya);
 getchar ();
}
{}
Вот какое-то несерьёзное поведение компилятора g++; все знают, что поля protected базового класса наследуются производными, а значит, в классе sinn просто-таки ОБЯЗАНА присутствуовать переменная peremennaya, но её там нет! Нет её и всё, ибо

C++
1
peremennaya= 11;
Приводит к ошибке. Зато

C++
1
2
 otets<T>::peremennaya= 11;
 sinn<T>::peremennaya= 11;
компилится, в то время, как всё вот это:
otets<int>:eremennaya;
sinn<int>:eremennaya;
peremennaya;

НАходится ПО ОДНОМУ адресу, а значит, логично просто квалифицировать это поле как
peremennaya;

Не получается. Почему?

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Блин, MSVC без проблем компилит;
C++
1
2
3
otets<T>::peremennaya= 11;
 sinn<T>::peremennaya= 11;
peremennaya= 11;
придётся, наверное, прогнуться под g++ и не писать:

C++
1
peremennaya= 11;
, я разачаровываюсь в g++


Ну и сразу вопрос, как грамотнее будет писать для компиляторосовместимости:
C++
1
2
3
4
template <class T>
void sinn<T>::f () {
 otets<T>::peremennaya= 11;
}
или

C++
1
2
3
4
template <class T>
void sinn<T>::f () {
  sinn<T>::peremennaya= 11;
}
, имея ввиду, что это суть одно и то же? Спасибо

Добавлено через 17 минут
Вообще вся эта катавасия опять определяется template <class T>! Уибраем сие и всё компилится нормально!
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
class otets {
 public:
  int peremennaya;
};
 
class sinn: public otets {
 void  f ();  
};
 
void sinn::f () {
 otets::peremennaya= 11;
 sinn::peremennaya= 11;
 peremennaya= 11;
};
 
int main() {
 sinn h;
 printf ("%x\n", &h.otets::peremennaya);
 printf ("%x\n", &h.sinn::peremennaya);
 printf ("%x\n", &h.peremennaya);
 getchar ();
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.06.2011, 22:52     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит!
Посмотрите здесь:

Есть базовый и производный класс, в базовом определена функция, необходимо её объявить в производном! - C++
Как-то так, что ли: class x { public: void f_0 (){}; }; class y: public x { public: //Тут у меня пойдёт...

Почему сын может спокойно работать с полями privat отцовского класса (опять template <class T> воду мутит!) - C++
Сабж class otets { public: otets (){}; private: int znach; }; template &lt;class T&gt; class sinn: public otets {

В базовом классе вводится символьный массив, а в производном - проверка на максимальную длину строки - C++
Здравствуйте. Помогите найти ошибку при наследовании класса. Есть такая проблема - в базовом классе вводится символьный массив, а в...

Невозможно обратиться к protected член, объявленному в классе "Counter" - C++
typedef unsigned int uint; class Counter { protected: ...

Template argument required for class "LinkedListIterator" - C++
#ifndef LINKEDLIST_H #define LINKEDLIST_H #include &lt;iostream&gt; using namespace std; template &lt;typename Type&gt; class...

Наследование, получить производный класс "интервал времени" - C++
Привет. Производный класс состоит из-двух полей. public &amp; private хочу в производном классе получить эти же поля, как public и...

Наследование классов: почему производный класс не учитывает данные, введенные в базовом? - C++
Почему при компилляции производный класс не учитывает данные, введенные в базовом? #include &lt;iostream&gt; using namespace std; ...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
schdub
2940 / 1284 / 238
Регистрация: 19.01.2009
Сообщений: 3,358
Завершенные тесты: 1
13.06.2011, 01:06     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! #2
Цитата Сообщение от kravam Посмотреть сообщение
Ну и сразу вопрос, как грамотнее будет писать для компиляторосовместимости
C++
1
2
3
// ...
this->peremennay = 11;
// ...
Это происходит из-за особенности разрешения неквалифицированных имен внутри шаблонов. Согласно стандарту, компилятор обязан производить поиск там где объявлен или определен шаблон, причем в зависимых базовых классах, поиск не производится.

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
#include <iostream>
 
template <class T> class Base {
protected:
    int foo;
public:
    Base() {
        std::cout << "Base::foo address = " << & this->foo << std::endl;
    }
};
 
template <class T> class Derived : public Base<T> {
public:
    Derived() {
        std::cout << "Derived::foo address = " << & this->foo << std::endl;
    }
 
    void  bar (int value);
};
 
template <class T> void Derived<T>::bar (int value) {
    this->foo = value;
    std::cout << std::endl
        << "Base<T>::foo value " << Base<T>::foo << std::endl
        << "Derived<T>::foo value " << Derived<T>::foo << std::endl
        << "this->foo value " << this->foo << std::endl;
}
 
int main() {
    Derived<int> h;
    h.bar(666);
    return 0;
}
Код
oleg@oleg-laptop:~$ cd src/tmp
oleg@oleg-laptop:~/src/tmp$ g++ main.cpp
oleg@oleg-laptop:~/src/tmp$ ./a.out
Base::foo address = 0xbfb82220
Derived::foo address = 0xbfb82220

Base<T>::foo value 666
Derived<T>::foo value 666
this->foo value 666
oleg@oleg-laptop:~/src/tmp$
kravam
быдлокодер
1691 / 878 / 44
Регистрация: 04.06.2008
Сообщений: 5,423
13.06.2011, 02:25  [ТС]     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! #3
schdub, тут не ошибка?
причем в зависимых базовых классах, поиск не производится.
schdub
2940 / 1284 / 238
Регистрация: 19.01.2009
Сообщений: 3,358
Завершенные тесты: 1
13.06.2011, 13:36     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! #4
Цитата Сообщение от kravam Посмотреть сообщение
schdub, тут не ошибка?
нет.

вот классический пример:
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
#include <iostream>
 
int foo;
 
template <typename T> class Base {
public:
    int foo;
};
 
template <typename T> class Derived : public Base<T> {
public:
    int get_foo () const {
        return foo;
    }
};
 
int main() {
 
    foo = 666;
 
    Derived<int> h;
    h.foo = 999;
 
    std::cout << h.get_foo() << std::endl;
    return 0;
}
Программа напечатает значение переменной foo из глобальной области видимости.


теперь меняем реализацию get_foo() на:
C++
1
2
3
    int get_foo () const {
        return this->foo;
    }
И в выводе получаем то что ожидали .
OstapBender
583 / 521 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
13.06.2011, 13:40     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! #5
у меня в обоих случаях выводит 999
schdub
2940 / 1284 / 238
Регистрация: 19.01.2009
Сообщений: 3,358
Завершенные тесты: 1
13.06.2011, 13:43     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! #6
Цитата Сообщение от OstapBender Посмотреть сообщение
у меня в обоих случаях выводит 999
Компилятор? Мы обсуждаем g++.
OstapBender
583 / 521 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
13.06.2011, 13:47     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! #7
sry guys
schdub
2940 / 1284 / 238
Регистрация: 19.01.2009
Сообщений: 3,358
Завершенные тесты: 1
13.06.2011, 13:58     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! #8
Более подробно об этом аспекте можно почитать, например, у Александреску и Саттера в их книге "Стандарты программирования на С++" стр. 138 (начиная с последнего абзаца).
C++ Coding Standarts
Избегайте зависимости от зависимых имен. Говоря неформально, зависимое имя — это имя, которое каким-то образом упоминает параметр шаблона. Многие компиляторы не поддерживают "двухфазный поиск" для зависимых имен из стандарта C++, а это означает, что код шаблона, использующий зависимые имена, будет вести себя по-разному на разных компиляторах, если только не принять меры для полной определенности при использовании зависимых имен. В частности, особого внимания требует наличие зависимых базовых классов, когда шаблон класса наследуется от одного из параметров этого шаблона (например, Т в случае template<typename T>class C:T{} или от типа, который построен с использованием одного из параметров шаблона (например, Х<Т> в случае template<typename T>class C:X<T>{}.

Коротко говоря, при обращении к любому члену зависимого базового класса необходимо всегда явно квалифицировать имя с использованием имени базового класса или при помощи this->. Этот способ можно рассматривать просто как некую магию, которая заставляет все компиляторы делать именно то, что вы от них хотите.

C++
1
2
3
4
5
6
7
8
9
10
11
12
template<typename T>
class С : Х<Т> {
    typename Х<Т>::SomeType s;  // использование вложенного
                                // типа (или синонима
                                // typedef) из базового
                                // класса
public:
    void f() {
        X<T>::baz();            // Вызов функции-члена
                                // базового класса
        this->baz();            // Альтернативный способ
};
kravam
быдлокодер
1691 / 878 / 44
Регистрация: 04.06.2008
Сообщений: 5,423
13.06.2011, 20:55  [ТС]     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! #9
schdub, я хотел узнать а ОТ ЧЕГО ЗАВИСИТ базовый класс, почему и переспросил.
Просто производный зависит от базового. А базовый от чего?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.06.2011, 22:05     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит!
Еще ссылки по теме:

Базовый класс "Летательный аппарат" и производные классы Ракета и Самолет - C++
Определить абстрактный базовый класс &quot;Летательный аппарат&quot; содержащий данные, описывающие название, стартовую массу аппарата. В этом...

"динамически выделяет массив указателей на базовый класс" - как это понять? - C++
Что значит вообще массив на класс? Я не совсем понимаю, мы ведь оперируем понятием объекта, а класс - это всего лишь тип. Нам нужно создать...

Базовый класс "Строка" отказывается работать - C++
не могу понять в чем проблема, базовый класс отказывается работать. main #include &lt;cstdlib&gt; #include &lt;iostream&gt; #include...

Создать базовый класс "транспортное средство" - C++
Создать базовый класс «транспортное средство” , в котором определены след. свойства: • Название транспортного средства (задается в...

Создать базовый класс "Грузоперевозчик" - C++
Создать базовый класс &quot;Грузоперевозчик&quot; и произвольные классы &quot;Поезд&quot;, &quot;Автомобиль&quot;. Определить время и стоимость перевозки для указанных...


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

Или воспользуйтесь поиском по форуму:
schdub
2940 / 1284 / 238
Регистрация: 19.01.2009
Сообщений: 3,358
Завершенные тесты: 1
13.06.2011, 22:05     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! #10
Он зависит от параметра шаблона.

Подробнее можно почитать у Ray Lischner - С++ In a Nutshell (7.8.1 Зависимые имена)

Или в стандарте у мну только n1905 Working Draft
14.6.2 Dependent names
Inside a template, some constructs have semantics which may differ from one instantiation to another. Such a construct depends on the template parameters. In particular, types and expressions may depend on the type and/or value of template parameters (as determined by the template arguments) and this determines the context for name lookup for certain names. Expressions may be type-dependent (on the type of a template parameter) or value-dependent (on the value of a non-type template parameter).
Yandex
Объявления
13.06.2011, 22:05     базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит!
Ответ Создать тему
Опции темы

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