有人能想出一个很好的方法让下面的代码工作吗? (再次,这是一种令人难以置信的简化方式)
template <class f, class g> class Ptr;
class RealBase
{
};
template <class a, class b, class c = Ptr<a,b> >
class Base : public RealBase
{
public:
Base(){};
};
template <class d, class e>
class Derived : public Base <d,e>
{
public:
Derived(){};
void DerivedMethod(){};
};
template <class f, class g>
class Ptr
{
public:
Ptr(){};
Ptr(Base<f,g,Ptr<f,g> >* a){in = a;};
Base<f,g,Ptr<f,g> >* operator->()
{
return in;
};
private:
Base<f,g,Ptr<f,g> >* in;
};
typedef Derived<double,double> DDerived;
int main()
{
Base<int,int> b = Base<int,int>();
Derived<double,double> d = Derived<double,double>();
DDerived dd = DDerived();
Ptr<double,double> p(&dd);
p->DerivedMethod();
return 1;
}
目前编译器因为Base&lt;&gt;而呻吟没有DerivedMethod();
修改
我确实理解这里的问题,我在第一种情况下缺乏解释是不好的(我很匆忙)。 [顺便说一下,这是非常简化的代码,是的,为了简单起见,我没有实际做任何事情的析构函数或方法。只是忽略它,它对问题没有任何影响。]
我需要发生的是,只处理派生类(D_Derived)的迭代器(此处未详述)需要访问派生类中包含的方法而不是基类。简单地将此方法引入基类并不是一个真正的选择,因为如果我必须这样做,这个错误将会发生很多。 (在真正的基类上构建了大约10个类,它们都有自己的派生方法。就像其中的20个。每个。)
有人能想到另一种实现此功能的方法吗?
答案 0 :(得分:2)
此代码不起作用,因为模板类Ptr返回基类模板的对象而不是派生模板类。派生方法是派生模板的一部分,因此会引发编译错误。如果DerivedMethod是基本模板的一部分,那么此代码将起作用
答案 1 :(得分:1)
这是有道理的。 Base没有这样的方法(DerivedMethod)。如果DerivedMethod是基类的虚函数(可能是pure
),它就可以工作。
答案 2 :(得分:1)
编译器是对的。为了能够访问方法,必须以编译器看到的类型声明此方法(这称为变量的静态类型)。在您的情况下,此类型为Base<…>
,并且编译器不知道它是其他类型。
答案 3 :(得分:1)
使用抽象类和成员名称很难弄清楚你真正想要实现的目标。如果您真的必须将Ptr
中的指针视为D_Derived
,请将访问者成员添加到Ptr
并使用类型转换:
class Ptr {
...
Base<f,g,Ptr<f,g> >* get() {
return in;
}
};
...
D_Derived* ptr = dynamic_cast<D_Derived*>(p.get());
if (ptr) {
ptr->DerivedMethod();
}
编辑:正如Konrad Rudolph指出的那样,为了使用动态强制转换,您必须向基类添加一个虚方法。
实际上,为每个要用作基类的类定义虚拟析构函数是一个好习惯,以确保调用派生类的析构函数(More Information)。
class RealBase {
public:
virtual ~RealBase() {}
};
答案 4 :(得分:0)
行。在尝试了大约10种不同的方法(static_cast
,reinterpret_cast
等)之后,您可以将它投射出来。
int main()
{
Base<int,int> b = Base<int,int>();
Derived<double,double> d = Derived<double,double>();
DDerived dd = DDerived();
Ptr<double,double> p(&dd);
DDerived * fauxpointer;
fauxpointer = (DDerived\*) &(*p);
fauxpointer->DerivedMethod();
return 1;
}
讨厌。但它确实有效,而这一切都很重要。
向所有重复这个问题的人欢呼。