기본 등급 멤버 데이터에 대한 파생 된 템플릿 클래스 액세스
-
13-09-2019 - |
문제
이 질문은 이 스레드.
다음 클래스 정의 사용 :
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
. 이것을 피할 수있는 방법이 있습니까? 코드를 단순화하기 위해 '사용'명령문/지시문이 템플릿 클래스 메소드에서 작동 할 수 있습니까?
편집하다:
범위 문제는이> 구문으로 변수를 자격으로하여 해결됩니다.
해결책
당신이 사용할 수있는 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 라이트 의이 항목.
다른 팁
여기서 기본 클래스는 비 의존적 기본 클래스가 아닙니다 (템플릿 인수를 모르고 결정할 수있는 완전한 유형을 가진 사람). _foo_arg
비 의존적 이름입니다. Standard 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
}
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();
}