Я имею для следующей ситуации:
template <class K> class A
{
public:
int a;
};
class B
{
public:
virtual void DoSomething() = 0;
};template <class K> class C : public A<K>, public B
{
public:
virtual void DoSomething()
{
a = 3; // ***
}
};
Теперь это работает на MSVC, однако gcc сообщает мне строку с 3 звездами: «ошибка:« a »не было объявлено в этой области». Я понял, что могу заменить строку на
A::a = 3;
и это работает на GCC (хорошо MINGW), а также. Нужно ли постоянно добавлять исходное имя класса для соответствия стандарту? Я думал, я должен добавить его, только если имена конфликтуют иначе.
Я использую mingw32 (gcc) 4.8.1.
Теперь это имеет смысл …
GCC прав, а MSVC не прав. Это не должно работать, потому что a
является зависимый от шаблона но выражение a;
не является.
То есть смысл, который вы намереваетесь a
зависит от аргумента шаблона (в вашем случае K
), но содержащееся в нем выражение — нет. И так как компилятор не может быть уверен, что создание экземпляров A<K>
будет иметь член по имени a
Это просто предполагает, что это не так.
Есть несколько простых решений, все они включают использование зависимого от шаблона выражения, поэтому решите a
:
this->a = 3; //my favourite
A<K>::a = 3; //you found this one
ПРИМЕР:
Давайте посмотрим пример того, почему это не должно работать:
template <typename K> struct A
{
int a;
};
int a; //global variable to make things more interesting
template <typename K> struct B : A<K>
{
void foo()
{
a = 3; //does it refer to A<K>::a or ::a?
}
};
//template specialization of A<int>
template <> struct A<int>
{
};
B<float> bf; // what does bf.foo() do?
B<int> bi; //and bi.foo()?
Также вы можете сделать противоположную ситуацию:
template <typename K> struct A
{
};
int a; //global variable to make things more interesting
template <typename K> struct B : A<K>
{
void foo()
{
a = 3; //does it refer to A<K>::a or ::a?
}
};
//template specialization of A<int>
template <> struct A<int>
{
int a; //now the member variable is in the specialization
};
B<float> bf; // what does bf.foo() do?
B<int> bi; //and bi.foo()?
Как вы можете видеть, стандартное поведение C ++ обеспечивает вашу защиту, поэтому код, который вы пишете в шаблоне, всегда будет ссылаться — более или менее — на одно и то же:
a
: всегда будет переменной non template (в данном случае глобальной), если она доступна. Если нет, то это ошибка компилятора.this->a
: всегда будет переменной-членом, если она доступна. Если нет, ошибка компилятора.Других решений пока нет …