Форум программистов, компьютерный форум, киберфорум
Наши страницы

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

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

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

12.06.2011, 22:52. Просмотров 1284. Ответов 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 ();
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.06.2011, 22:52
Здравствуйте! Я подобрал для вас темы с ответами на вопрос базовый и производный класс, в базовом объявлена переменная "protected", она недоступна по имени в производном классе! template <class T> воду мутит! (C++):

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

Указатели в базовом классе на базовый класс и производный класс - C++
Пишу контейнер &quot;Бинарное дерево поиска&quot; для частотного словаря. С самим контейнером особо вопросов нету. Вопрос по поводу элементов в...

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

Создать класс "Шар", заданный радиусом, и определить производный класс "Окружность" - C++
Создать класс шар, заданный радиусом. Определить производный класс окружности. Предусмотреть виртуальную функцию для вычисления площади...

Базовый класс "Источник напряжения", производные классы "Цепь" и "Аккумулятор" - C++
Дали задачу по программированию: составить класс &quot;Источник напряжения&quot;, для которого нужно реализовать два производных класса: &quot;Цепь&quot; и...

Базовый класс "многоугольник" и производные классы "треугольник" и "прямоугольник" - C++
Не могу понять как реализовать данное задание. Создать 1 базовый класс и несколько производных.Все небольшие ф-ии сделать встроенными...

9
schdub
2959 / 1304 / 239
Регистрация: 19.01.2009
Сообщений: 3,424
Завершенные тесты: 1
13.06.2011, 01:06 #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$
1
kravam
быдлокодер
1701 / 888 / 45
Регистрация: 04.06.2008
Сообщений: 5,498
13.06.2011, 02:25  [ТС] #3
schdub, тут не ошибка?
причем в зависимых базовых классах, поиск не производится.
0
schdub
2959 / 1304 / 239
Регистрация: 19.01.2009
Сообщений: 3,424
Завершенные тесты: 1
13.06.2011, 13:36 #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;
    }
И в выводе получаем то что ожидали .
0
OstapBender
584 / 523 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
13.06.2011, 13:40 #5
у меня в обоих случаях выводит 999
0
schdub
2959 / 1304 / 239
Регистрация: 19.01.2009
Сообщений: 3,424
Завершенные тесты: 1
13.06.2011, 13:43 #6
Цитата Сообщение от OstapBender Посмотреть сообщение
у меня в обоих случаях выводит 999
Компилятор? Мы обсуждаем g++.
0
OstapBender
584 / 523 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
13.06.2011, 13:47 #7
sry guys
0
schdub
2959 / 1304 / 239
Регистрация: 19.01.2009
Сообщений: 3,424
Завершенные тесты: 1
13.06.2011, 13:58 #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();            // Альтернативный способ
};
2
kravam
быдлокодер
1701 / 888 / 45
Регистрация: 04.06.2008
Сообщений: 5,498
13.06.2011, 20:55  [ТС] #9
schdub, я хотел узнать а ОТ ЧЕГО ЗАВИСИТ базовый класс, почему и переспросил.
Просто производный зависит от базового. А базовый от чего?
0
schdub
2959 / 1304 / 239
Регистрация: 19.01.2009
Сообщений: 3,424
Завершенные тесты: 1
13.06.2011, 22:05 #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).
1
13.06.2011, 22:05
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.06.2011, 22:05
Привет! Вот еще темы с ответами:

Создать класс "Квадрат" и производный класс "Правильная пирамида" - C++
Заранее спасибо за помощь)

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

typeid определяет тип указателя на базовый класс, как тип "базовый класс". Вне зависимости от присвоенного ему значения - C++
Вот код: #include &lt;iostream&gt; #include &lt;string&gt; #include &lt;conio.h&gt; #include &lt;windows.h&gt; #include &lt;typeinfo&gt; using...

Для класса "Футболист" создать производный класс "Нападающий" - C++
помогите плиз написать главную функцию и внешний метод и посмотрите ошибки класс ФУТБОЛИСТ с атрибутами: фамилия, название команды,...


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

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

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