【问题标题】:Inheritance issues with template classes模板类的继承问题
【发布时间】:2009-03-09 12:45:02
【问题描述】:

谁能想出一个好方法来让下面的代码工作? (这又是一种非常简单的方法)



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 没有 DerivedMethod();

编辑

我确实理解这里的问题,因为在第一种情况下缺乏解释(我很着急),这很糟糕。 [顺便说一句,这是非常精简的代码,是的,为了简单起见,我没有实际执行任何操作的析构函数或方法。忽略这一点,对问题没有影响。]

我需要做的是,仅处理派生类 (D_Derived) 的迭代器(此处未详细说明)需要访问包含在派生类而不是基类中的方法。简单地将这个方法插入基类并不是一个真正的选择,因为如果我必须这样做,这个错误将会发生很多。 (大约有 10 个类建立在真正的基类上,它们都有自己的派生方法。就像其中的 20 个。每个。)

谁能想到另一种方法来实现此功能?

【问题讨论】:

    标签: c++ inheritance


    【解决方案1】:

    此代码不起作用,因为模板类 Ptr 返回的是基模板类的对象,而不是派生模板类的对象。派生方法是派生模板的一部分,因此会引发编译错误。而如果 DerivedMethod 是基本模板的一部分,则此代码将起作用

    【讨论】:

      【解决方案2】:

      这是有道理的。 Base 没有这样的方法(DerivedMethod)。如果 DerivedMethod 是基类的虚函数(可以是 pure),它就可以工作。

      【讨论】:

        【解决方案3】:

        编译器是对的。为了让您能够访问一个方法,该方法必须以编译器看到的类型声明(这称为变量的静态类型)。在你的情况下,这种类型是 Base&lt;…&gt; 并且编译器不知道它是别的什么。

        【讨论】:

          【解决方案4】:

          使用抽象类和成员名称很难弄清楚您真正想要实现的目标。如果您确实必须将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() {}
          };
          

          【讨论】:

          • 这里不能使用dyanmic_cast!该类没有虚拟成员,因此没有运行时类型信息!
          • 你说得对,我错过了这一点。编辑了我原来的帖子——谢谢。
          • 注:这段代码中缺少大量的方法,为了便于理解,它们的名称都非常简单。它们都有析构函数。
          • 如果它们都有析构函数,那么声明它们virtual真的很重要,如果你还没有这样做的话!
          • 咳咳。无关紧要。这是示例代码。作为一般规则,我不是在询问关于我的编码风格的提示,我知道我在做什么。我要的是一种做我上面演示的方法。
          【解决方案5】:

          好的。在尝试了大约 10 种不同的方法(static_cast、reinterpret_cast 等)之后,您就可以投射了。

          int main()
          {
              Base&lt;int,int> b = Base&lt;int,int>();
              Derived&lt;double,double> d = Derived&lt;double,double>();
              DDerived dd = DDerived();
              Ptr&lt;double,double> p(&dd);
              DDerived * fauxpointer;
              fauxpointer = (DDerived\*) &(*p);
              fauxpointer->DerivedMethod();
              return 1;
          }
          

          恶心。但它确实有效,仅此而已。

          向所有向我重复这个问题的人干杯。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-08-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多