【问题标题】:overriding push_back c++覆盖 push_back c++
【发布时间】:2012-12-12 09:42:37
【问题描述】:

我有一个名为Path 的类扩展std::vector<Square *>,其中Square 也是我创建的一个类。 Path 将作为实体穿越 2D 环境的指南。我需要获得最长路径和最短路径,因此我希望在Path 中找到两个Squares 之间的平方数。为此,我觉得重载std::vector<Square *>::push_back(const value_type &__x) 是有益的,尽管我不确定它的语法是什么。我目前正在尝试这个:

class Path : public std::vector<Square *>
{   //... functional stuff, not relevant. 
    int length;
public:
    push_back(const value_type &__x)
    {   Square *last_square = this->at(this->size() - 1);

        // how do I call super class push_back?
        // however that works, I push back &__x square here.

        Square *most_recent = (Square *)&__x;
        int delta_x = compare_distance(last_square, most_recent);
        length += delta_x;
    };
    int path_length() { return length; };
};

当然,我想我可以只为超类编写一个调用 push_back 的方法,但我觉得重写该函数更简洁,而且学习如何正确重写 stl 对我来说是一个好习惯功能。

谢谢!

【问题讨论】:

  • Nooooooooooooooooooo,你继承自 std::vector。用火杀死它!!1
  • 保留带有双下划线的标识符。你不应该使用它们。标准库使用它们是因为它们是为标准库保留的。
  • 谢谢大家!我想我从来没有想过从 STL 继承可能是不好的做法。

标签: c++ inheritance vector overriding overloading


【解决方案1】:

另外,学习如何正确覆盖 stl 函数对我来说是个好习惯。

其实不然。

STL 容器不应该被继承(没有virtual 方法),因此好的做法是使用组合并为使用 STL 容器方法的类提供一个有意义的接口来完成它目标。

【讨论】:

  • 哈哈,知道这不是好习惯对我有好处。谢谢马修
【解决方案2】:

您可以覆盖基类中定义的虚拟函数以获得动态多态性 - 在运行时确定的类型相关行为。

但是,STL 容器使用模板和非虚拟函数来提供 静态多态性 - 在编译时确定的类型相关行为。没有要覆盖的虚函数,因此从它们继承没有什么意义。

特别是,您的类隐藏基类函数;通过指向std::vector 而不是Path 的指针/引用调用push_back 的任何人都不会调用您的版本,这很可能会导致令人困惑的错误。更好的方法是合成:

class Path {                        // no inheritance
    std::vector<Square *> squares;  // composition instead
public:
    void push_back(Square * x)      // Don't use __ in identifiers
    {
        squares.push_back(x);
        // do other stuff
    }
};

为了回答代码 cmets 中的问题,如果您确实出于某种奇怪的原因想要使用继承,您可以通过使用基类名称限定成员名称来调用基类版本:

std::vector<Square*>::push_back(x);

【讨论】:

    【解决方案3】:

    您使用std::vector 的事实只是一个实现细节。它也可以是std::list,甚至是std::set

    这应该给你一个线索,你不应该对这种类型过于强烈地承诺。

    聚合而不是继承。你继承被重用,我认为这不是你需要的。

    此外,使用标准容器的正确方法是不要从它们继承。它们没有虚拟析构函数,也没有要覆盖的虚拟函数。

    【讨论】:

      【解决方案4】:

      要添加到其他的,在这种情况下,您将使用组合或私有继承(在术语中实现)。

      根据经验,提出问题并根据哪个更真实决定使用什么:

      • 路径是根据 std::vector 实现的

      • 路径是一个 std::vector

      如果“Path is a std::vector”更准确(因此 Path 不能是 std::list、或 std::deque 或 MyFunnyContainer),则从 std::vector 派生。 如果“路径是根据 std::vector 实现的”更准确,请使用组合或私有继承。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-11
        • 1970-01-01
        • 2013-10-21
        • 1970-01-01
        • 2017-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多