【问题标题】:C++ Parent class method callC++父类方法调用
【发布时间】:2009-10-14 17:57:11
【问题描述】:

我正在创建一个从 STL 库继承队列的新类。该类的唯一添加是向量。该向量将具有与队列相同的大小,并将存储一些整数值,这些值将对应于队列中的每个对象。

现在,我想重写 pop() 和 push(),但我只是想为父类的方法添加更多功能。

例如。当对队列对象调用 pop() 时,我还想从向量中弹出一个对象。当对队列对象调用 push() 时,我还想在向量中插入一个新对象。

我该怎么做???

#include <iostream>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

template <typename type>
class CPU_Q : public queue<type>
{

  public:
    vector<int>  CPU_TIME;

    void increaseTime()
    {
      for(int ndx = 0; ndx < CPU_TIME.size(); ndx++)
      {
        CPU_TIME[ndx]++;
      }
    }

  void push(type insertMe)
  {
    //This is what I want to do
    super::push(); // or queue::push(); maybe?
    CPU_TIME.push_back(0);
  }
  void pop()
  {
    //Something very similar to push()
  }
}

非常感谢提前

-三

【问题讨论】:

  • C++ 没有super 关键字的原因可能是C++ 中有多重继承。你可以有几个基类/超类。所以你改用基类的正确类型:queue&lt;type&gt;::push(insertMe)。但是,请确保您阅读了解释为什么从 STL 容器继承可能不是您想要的答案。
  • 您是否也考虑过简单地将这些值放入自己的结构中,这样您就可以始终保证相关值一起添加和删除?

标签: c++ inheritance


【解决方案1】:

你问的是:

void push(type insertMe){
      //This is what I want to do
      super::push(); // or queue::push(); maybe?
      CPU_TIME.push_back(0);
}

这更像是:

void push(type insertMe) { 
   queue<type>::push(insertMe);
   CPU_TIME.push_back(0);
}

除非您可能希望通过 const 引用接受参数:

void push(type const &insertme) { 
    queue<type>::push(insertMe);
    CPU_TIME.push_back(0);
}

也就是说,标准容器类并不是真正为继承而设计的(例如,它们没有虚拟 dtor),因此您必须小心这一点——例如当您销毁它时,您需要将静态类型作为派生类型;如果(例如)通过指向基类的指针销毁一个,则会得到未定义的行为。

【讨论】:

  • 你是说从队列派生是有效的吗?
  • 有足够的照顾,是的。我不确定我是否真的会推荐它,但没有什么可以让它自动失效。
  • 从队列派生肯定是not有效的,但也不是“不可能”。我建议将队列保留为实例变量并转发任何 push()/pop() 调用。
  • 我想这取决于您所说的“肯定无效”是什么意思。在任何功能正确的 C++ 编译器都必须接受代码的情况下,它是“有效的”。从他的描述来看,从设计的角度来看,它甚至可能是“有效的”——他没有表现出足够的绝对确定性,但你可能基本上可以在允许队列的任何地方替换他的派生类(唯一明显的例外是通过指针销毁队列)。
  • 实际上队列和堆栈(适配器类)都有一个受保护的成员变量c。这意味着它们可以安全地继承自。它只是很少需要。
【解决方案2】:

STL 队列类不打算使用继承进行扩展。查看here 了解更多信息。除此之外std::queue 有多个模板参数。除了继承,您还可以使用 std::queue 作为模板类 CPU_Q 的成员,如下所示:

template<typename T>
class CPU_Q
{
  std::queue<T> q;
public:
  void push( T val ) 
  { 
    q.push( val );
    // additional work
  }
};

【讨论】:

  • 这是包含而不是继承,这可能更好,但可能需要一些解释才能理解。
  • 注意:queue 和 stack 都有一个受保护的成员。这意味着在某种情况下继承是有意义的。但是,我仍然同意构图是首选。
【解决方案3】:

简单的答案是不可能。 STL 容器类不是为继承而设计的。他们的析构函数不是虚拟启动的。如果你真的想做这样的事情,那么编写一个“包含”队列和向量的新类,并在任何地方使用这个类。顺便说一句,与 Java 不同,C++ 中没有 super 关键字。如果你想调用基类方法使用BaseClassName::methodName();

【讨论】:

  • 嗯,有可能。不可能将生成的类视为std::queue&lt;T&gt;。经典的多态性 不适用于 STL。 (但是,编译时多态确实如此。)
  • 是的..我的意思是你不能使用动态绑定重新路由对队列的 pop() 等方法的调用。
  • 我不明白最新的反对票..答案有问题吗?
  • 这不是“不可能”。它不适用于大多数用例并不会改变这一点。
  • @gf:“大多数用例”对我来说似乎很可疑。对我来说,我通常根本不传递容器。我只传递迭代器。另外,如果你传递容器,为什么要限制自己使用std::queue?只需将此作为模板参数,任何其他提供所需接口的容器也可以。所有这些情况都适用于从 std::queue 继承的容器,即使它们覆盖了任何函数。唯一不起作用的是动态多态性。
【解决方案4】:

除非您的新类与std::queue 具有is-a 关系,否则我会强烈考虑封装队列和向量,并提供转发到适当的std::queue/std::vector 的方法方法,按照您希望它们被调用的顺序。

此外,如果您希望这个新类与标准算法兼容,则必须实现一个 begin() 和 end() 方法,该方法返回一个能够遍历您的数据结构的 iterator 类型;不过,您也许可以使用std::queue/std::vector 上的现有方法来完成此操作。

【讨论】:

    猜你喜欢
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 2011-01-03
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多