Полученный доступ класса-шаблона к данным-членам базового класса
42727 просмотра
3 ответа
Этот вопрос является продолжением вопроса, заданного в этой теме .
Используя следующие определения классов:
template <class T>
class Foo {
public:
Foo (const foo_arg_t foo_arg) : _foo_arg(foo_arg)
{
/* do something for foo */
}
T Foo_T; // either a TypeA or a TypeB - TBD
foo_arg_t _foo_arg;
};
template <class T>
class Bar : public Foo<T> {
public:
Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
: Foo<T>(bar_arg) // base-class initializer
{
Foo<T>::Foo_T = T(a_arg);
}
Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
: Foo<T>(bar_arg)
{
Foo<T>::Foo_T = T(b_arg);
}
void BarFunc ();
};
template <class T>
void Bar<T>::BarFunc () {
std::cout << _foo_arg << std::endl; // This doesn't work - compiler error is: error: ‘_foo_arg’ was not declared in this scope
std::cout << Bar<T>::_foo_arg << std::endl; // This works!
}
При доступе к членам базового класса шаблонного класса кажется, что я всегда должен явно определять членов, используя синтаксис шаблонного стиля Bar<T>::_foo_arg
. Есть ли способ избежать этого? Может ли оператор / директива using использовать метод класса шаблона для упрощения кода?
Редактировать:
Проблема с областью решается путем определения переменной с синтаксисом this->.
Автор: Shamster Источник Размещён: 12.11.2019 09:04Ответы (3)
64 плюса
Вы можете использовать, this->
чтобы прояснить, что вы имеете в виду члена класса:
void Bar<T>::BarFunc () {
std::cout << this->_foo_arg << std::endl;
}
В качестве альтернативы вы также можете использовать " using
" в методе:
void Bar<T>::BarFunc () {
using Bar<T>::_foo_arg; // Might not work in g++, IIRC
std::cout << _foo_arg << std::endl;
}
Это дает понять компилятору, что имя элемента зависит от параметров шаблона, поэтому он ищет определение этого имени в нужных местах. Для получения дополнительной информации также см. Эту запись в C ++ Faq Lite .
Автор: sth Размещён: 13.07.2009 05:5023 плюса
Здесь базовый класс не является независимым базовым классом (что означает класс с полным типом, который может быть определен без знания аргументов шаблона), и _foo_arg
является независимым именем. Стандарт C ++ говорит, что независимые имена не ищутся в зависимых базовых классах.
Чтобы исправить код, достаточно сделать имя _foo_arg
зависимым, потому что зависимые имена можно искать только во время создания экземпляра, и в это время будет известна точная базовая специализация, которая должна быть изучена. Например:
// solution#1
std::cout << this->_foo_arg << std::endl;
Альтернатива заключается во введении зависимости с использованием квалифицированного имени:
// solution#2
std::cout << Foo<T>::_foo_arg << std::endl;
Необходимо соблюдать осторожность с этим решением, потому что если неквалифицированное независимое имя используется для формирования вызова виртуальной функции, то квалификация запрещает механизм виртуального вызова, и значение программы изменяется.
И вы можете принести имя из зависимого базового класса в производный класс один раз using
:
// solution#3
template <class T>
class Bar : public Foo<T> {
public:
...
void BarFunc ();
private:
using Foo<T>::_foo_arg;
};
template <class T>
void Bar<T>::BarFunc () {
std::cout << _foo_arg << std::endl; // works
}
Автор: songyuanyao
Размещён: 23.06.2014 02:33
1 плюс
Кажется, работает нормально в Visual C ++ 2008. Я добавил несколько фиктивных определений для упомянутых вами типов, но не дал источника. Остальное именно так, как вы выразились. Затем основная функция, которая BarFunc
должна быть создана и вызвана.
#include <iostream>
class streamable {};
std::ostream &operator<<(std::ostream &os, streamable &s) { return os; }
class foo_arg_t : public streamable {};
class a_arg_t : public streamable {};
class b_arg_t : public streamable {};
template <class T>
class Foo {
public:
Foo (const foo_arg_t foo_arg) : _foo_arg(foo_arg)
{
/* do something for foo */
}
T Foo_T; // either a TypeA or a TypeB - TBD
foo_arg_t _foo_arg;
};
template <class T>
class Bar : public Foo<T> {
public:
Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
: Foo<T>(bar_arg) // base-class initializer
{
Foo<T>::Foo_T = T(a_arg);
}
Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
: Foo<T>(bar_arg)
{
Foo<T>::Foo_T = T(b_arg);
}
void BarFunc ();
};
template <class T>
void Bar<T>::BarFunc () {
std::cout << _foo_arg << std::endl;
std::cout << Bar<T>::_foo_arg << std::endl;
}
int main()
{
Bar<a_arg_t> *b = new Bar<a_arg_t>(foo_arg_t(), a_arg_t());
b->BarFunc();
}
Автор: Daniel Earwicker
Размещён: 13.07.2009 05:31
Вопросы из категории :
- c++ What are the barriers to understanding pointers and what can be done to overcome them?
- c++ Какой самый простой способ для анализа файла INI в C ++?
- c++ Когда вы должны использовать «друг» в C ++?
- c++ Как вы очищаете переменную stringstream?
- templates Изменить шаблоны в Xcode
- templates Каковы различия между «универсальными» типами в C ++ и Java?
- templates Как добавить отражение в приложение C ++?
- templates Проверьте, имеет ли класс функцию-член с заданной сигнатурой
- inheritance Предпочитаете композицию наследству?
- inheritance Вызывать события C # извне класса-владельца?
- inheritance Хорошие причины запретить наследование в Java?
- inheritance Что «супер» делает в Python?
- scope Почему переменные не объявлены в «try» в области «catch» или «finally»?
- scope Как работают закрытия JavaScript?
- scope Область видимости переменной Bash
- scope Краткое описание правил оглавления?
- name-lookup Полученный доступ класса-шаблона к данным-членам базового класса
- name-lookup Распространение «typedef» из основанного на производный класс для «шаблона»
- name-lookup Why doesn't ADL find function templates?
- name-lookup В шаблонном производном классе, почему мне нужно квалифицировать имена членов базового класса с помощью "this->" внутри функции-члена?