代码之家  ›  专栏  ›  技术社区  ›  PypeBros vinay hunachyal

基类“class std::vector<…>”具有非虚析构函数

  •  2
  • PypeBros vinay hunachyal  · 技术社区  · 14 年前

    std::vector 这样它就可以充当一个容器,同时对其内容执行自定义操作。不幸的是,编译器抱怨析构函数不是虚拟的,我不能更改,因为它在标准库中。

    编辑 :派生类不涉及向量操作算法,只添加一些信息,例如图像向量的“元素宽度/高度”。举个例子,你可以想到

    class PhotoAlbum: public std::vector<Photo> {
        String title;
        Date from_time, to_time;
        // accessors for title and dates
        void renderCover(Drawable &surface);
    };
    

    如果你认为相册主要是一组图片,其中包含一些元数据(标题和时间)和相册特有的功能,例如将某张照片的缩略图渲染到一个表面上以制作相册封面。所以,这本相册是一本 Photo ,比它拥有的还要多——这样的收藏。

    我看不出我能从中得到什么好处 getPhotoVector() a中的方法 PhotoAlbum 那会有一个额外的“collection”字段。

    4 回复  |  直到 11 年前
        1
  •  10
  •   Steve Jessop    14 年前

    拥有一个带有非虚拟析构函数的公共基类是安全的 但是 如果有人用 new ,用 vector<...>*

    为了处理这个问题,而不必对用户施加这样的奇怪条件,最好的建议是,对于C++中的公共基类,析构函数应该是公共的和虚拟的,或者是保护的和非虚拟的。 http://www.gotw.ca/publications/mill18.htm ,准则4)。自从 std::vector 两者都不是,这意味着它不应该用作公共基类。

    如果你想在向量上定义一些额外的操作,那就是C++中的自由函数。有什么了不起的 . <algorithm> 包含对向量和其他容器的附加操作。

    vector using :

    #include <vector>
    #include <iostream>
    #include <stdexcept>
    
    class myvec : private std::vector<int> {
        size_t max_size;
      public:
        myvec(size_t m) : max_size(m) {}
        // ... other constructors
    
        void push_back(int i) {
            check(size()+1);
            std::vector<int>::push_back(i);
        }
        // ... other modified functions
    
        using std::vector<int>::operator[];
        // ... other unmodified functions
    
      private:
        void check(size_t newsize) {
            if (newsize > max_size) throw std::runtime_error("limit exceeded");
        }
    };
    
    int main() {
        myvec m(1);
        m.push_back(3);
        std::cout << m[0] << "\n";
        m.push_back(3); // throws an exception
    }
    

    不过,你还是要小心。C++标准不能保证哪些功能 调用重载的基类 myvec ,所以我修改过的函数就不适用了——这是非虚函数。我不能只是超载 resize() 完成后,我必须重载每一个改变大小的函数,让它们都调用 check (直接或通过打电话)。

    operator[] 无法更改向量的大小,因此在我的示例中,我可以安全地使用基类实现,并且只需重载可能更改大小的函数。但该标准不一定能为所有可能的派生类提供这种保证。

    总之, 不是设计为基类的,因此它可能不是一个性能非常好的基类。

    当然,如果使用私有继承,那么就不能通过 一个需要向量的函数。但那是因为 不是吗 向量-它的 push_back 矢量 矢量 没有虚拟析构函数,也没有 任何 虚拟功能。

    vector<int> *ptr = new myvec(1); ),那么你就进入了“你不应该”的领域。标准库并不能真正帮助你。

        2
  •  16
  •   Community Egal    7 年前

    std::vector 自定义容器的成员,然后将自定义操作实现为作用于 成员。这样,你就可以完全控制它了。除此之外, you should prefer composition over inheritance

        3
  •  1
  •   Starkey    14 年前

    也许用合成代替继承?你没有说为什么你要扩展向量,所以我不知道这是不是一个选择。

        4
  •  1
  •   John Dibling    14 年前

    可能吧。

    vector 以提供特殊功能。通常的方法是使用内置的算法和你自己的函数来提供这个特殊的功能。

    这样做而不是从 矢量

    矢量 . 的工作是维护对象的集合。不在这些对象上执行算法功能。从 矢量 矢量

    2) 它更符合“STL方式”的做事方式。这使得了解STL但可能不了解您的特殊类(其行为与STL集合不同)的人更容易在将来进行维护。

    3) 它更具可扩展性。一个正确编写的函子并不关心它作用于什么样的集合。如果有一天你因为某种原因想使用 list 矢量 ,如果您使用的是函子,那么重构要比重新实现一个新的特殊函数简单得多 列表

    4) 总体来说,它的设计比较简单,因此不易受到缺陷的影响,也更易于维护。