下面是一些代码,概述了我一直在努力解决的一个问题。最后一个问题(就目前的g++而言)是:“错误:'Foo-T‘没有在这个作用域中声明”,当执行Bar::Bar(...)构造函数例程。否则,我要学习的问题之一就是如何根据使用模板传递给派生类构造函数的参数来设置基类成员类型。如果有一种方法可以简单地通过将参数传递给派生类构造函数来设置基类成员类型(T Foo-T),我更希望这样做。到目前为止,我还看不到使用模板参数和匹配的派生类构造函数参数来完成此任务的方法。你能在下面的代码中找出我可以做得更好的地方来实现同样的目标吗?我对泛型编码和模板比较陌生。
#include <iostream>
typedef int a_arg_t;
typedef double b_arg_t;
typedef std::string foo_arg_t;
class TypeA {
public:
TypeA ();
TypeA (a_arg_t a) {
/* Do sosmething with the parameter passed in */
}
};
class TypeB {
public:
TypeB ();
TypeB (b_arg_t b) {
/* typeB's constructor - do something here */
}
};
// The base-class with a member-type to be determined by the template argument
template <class T>
class Foo {
public:
Foo (const foo_arg_t foo_arg) : _foo_arg(foo_arg) // initialize something here
{
/* do something for foo */
}
T Foo_T; // either a TypeA or a TypeB - TBD
foo_arg_t _foo_arg;
};
// the derived class that should set the basse-member type (T Foo_T)
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
{
// the initialization of Foo_T has to be done outside the initializer list because it's not in scsope until here
Foo_T = TypeA(a_arg); // if an a_arg_t is passed in, then we set the Foo_T to TypeA, etc.
}
Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
: Foo<T>(bar_arg)
{
Foo_T = TypeB(b_arg);
}
};
int main () {
b_arg_t b_arg;
a_arg_t a_arg;
foo_arg_t bar_arg;
Bar<TypeA> a (bar_arg, a_arg); // try creating the derived class using TypeA
Bar<TypeB> b (bar_arg, b_arg); // and another type for show
return 0;
}发布于 2009-07-13 09:20:50
当在派生(栏)构造函数中使用时,将不会在基类中查找Foo_T类型。
Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
: Foo<T>(bar_arg) // base-class initializer
{
Foo_T = TypeA(a_arg); TypeA, etc. // Won't compile, per the standard
}这是根据C++标准进行的,该标准规定非限定名通常是非依赖的,应该在完全定义模板时进行查找。
由于模板基类定义当时是未知的(可能会有模板的完全专门化实例稍后在编译单元中被拉入),所以不合格的名称永远不会被解析为依赖基类中的名称。
如果涉及模板时需要基类中的名称,则必须完全限定它们,或者使它们隐式依赖于派生类。
Foo< T >::Foo_T = TypeA(a_arg); // fully qualified will compile或者,使其依赖于
this->Foo_T = TypeA(a_arg);因为this使其依赖于模板,所以解析类型被推迟到模板实例化的“阶段2”(然后,基类也是完全已知的)
请注意,如果要使用基类中的函数,还可以添加using声明。
(栏内())
some_foo_func(); // wouldn't work either
using Foo<T>::some_foo_func;
some_foo_func(); // would work however发布于 2009-07-13 04:37:13
很抱歉帮不上忙,但如果不按照你说的做,我也看不到解决这个问题的办法:
到目前为止,我还看不到使用模板参数和匹配的派生类构造函数参数来完成此任务的方法。
你可能需要专门化一下:
template<>
Bar<TypeA>::Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
: Foo<TypeA>(bar_arg) // base-class initializer
{
// the initialization of Foo_T has to be done outside the initializer list because it's not in scsope until here
Foo_T = TypeA(a_arg); // if an a_arg_t is passed in, then we set the Foo_T to TypeA, etc.
}
template< class T>
Bar<T>::Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
: Foo<T>(bar_arg) // base-class initializer
{
// Throw exception?
}
template<>
Bar<TypeB>::Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
: Foo<TypeB>(bar_arg)
{
Foo_T = TypeB(b_arg);
}
template< class T >
Bar<T>::Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
: Foo<T>(bar_arg)
{
// Throw exception ?
}不幸的是,我现在无法访问编译器来检查这段代码,所以要小心。
回答你的问题/评论。我需要编译以下代码:
#include <iostream>
typedef int a_arg_t;
typedef double b_arg_t;
typedef std::string foo_arg_t;
class TypeA {
public:
TypeA () {}
TypeA (a_arg_t a) {}
};
class TypeB {
public:
TypeB () {}
TypeB (b_arg_t b) {}
};
template <class T>
class Foo {
public:
Foo (const foo_arg_t foo_arg) : _foo_arg(foo_arg) {}
T Foo_T; // either a TypeA or a TypeB - TBD
foo_arg_t _foo_arg;
};
// the derived class that should set the basse-member type (T Foo_T)
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 = TypeA(a_arg);
}
Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
: Foo<T>(bar_arg)
{
Foo<T>::Foo_T = TypeB(b_arg);
}
};
int main () {
b_arg_t b_arg;
a_arg_t a_arg;
foo_arg_t bar_arg;
Bar<TypeA> a (bar_arg, a_arg); // try creating the derived class using TypeA
Bar<TypeB> b (bar_arg, b_arg); // and another type for show
return 0;
}发布于 2009-07-13 06:55:37
当我第一次看你的代码时,我绝对确定你必须用部分专门化来解决这个问题。事实上,这种情况可能仍然存在,但是,我已经减少了复制您的错误所需的代码量,并观察到错误只发生在使用gcc编译时(我不知道我的大学运行的是哪个编译器版本),以及使用Visual Studio2003编译时-一切都很顺利。
以下代码复制了错误代码,但一个看似无害的微小更改将出人意料地消除它:
template <typename T>
class ClassA
{
public:
ClassA () {}
T vA;
};
template<typename T>
class ClassB : public ClassA<T>
{
public:
ClassB ()
{
vA = 6;
}
};
int main ()
{
ClassB<int> cb;
}现在,如果您从ClassB中删除模板声明,并让它直接从ClassA继承:
class ClassB : public ClassA<int>
{
public:
ClassB ()
{
vA = 6;
}
};然后更改cb的声明以匹配
ClassB cb;然后,错误就消失了,即使关于vA (或者在您的例子中是Foo_T)的作用域没有什么不同
我推测这是一个编译器错误,我想知道是否一个完全最新的gcc编译器仍然会遇到这个问题。
https://stackoverflow.com/questions/1117693
复制相似问题