派生到基类成员数据的模板类访问

这个问题是在这个线程中提出的问题的进一步推动。

使用以下类定义:

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->语法限定variables来解决。

你可以使用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; } 

这使编译器清楚地知道,成员名称取决于模板参数,以便在正确的位置search该名称的定义。 有关更多信息,请参阅C ++ Faq Lite中的此条目 。

这里的基类不是一个非依赖的基类(这意味着一个完整的types可以在不知道模板参数的情况下被确定), _foo_arg是一个非_foo_arg的名字。 标准C ++说,非依赖名称不在依赖基类中查找。

为了纠正这个代码, _foo_arg需要依赖_foo_arg这个名字就可以了,因为依赖名只能在实例化的时候才能_foo_arg ,并且在那个时候必须知道确切的基础专用化。 例如:

 // solution#1 std::cout << this->_foo_arg << std::endl; 

另一种方法是使用合格的名称引入依赖关系:

 // solution#2 std::cout << Foo<T>::_foo_arg << std::endl; 

必须小心这个解决scheme,因为如果使用不合格的非独立名称来形成一个虚拟函数调用,那么资格限制了虚拟调用机制和程序改变的含义。

你可以使用下面的方法从派生类中的一个从属基类中取一个名字:

 // 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中工作正常。我已经为您提到的types添加了一些虚拟定义,但没有提供源代码。 剩下的就是你所说的。 然后一个主要的function强制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(); }