【问题标题】:Polymorphism,STL,find and operator==多态性、STL、查找和运算符==
【发布时间】:2013-09-05 20:35:53
【问题描述】:

我遇到了问题。 我有一个 A 类,还有一个从 A 继承的类,我们称它为 B 类。 我有虚拟功能。 我想通过 operator== 将 A 和 B 与另一个 C 类进行比较。 如果我想要一个 A 的列表,让我们在 stl 列表中说, 我必须使用指向 A 的指针,所以它看起来像:

list<*A> list;

我也有:C something

但是现在,我不能使用这个功能:find(list.begin(),list.end(),something) 因为我不能使用 operator == 作为指针(*)。

我找到了一个解决方案,但我认为它不是最好的,所以我的问题是——我能做得更好吗?

    iter=list.begin();
    for(iter;iter!=list.end();++iter)
    {
        if((*iter).operator==(something)
            return ...
    }

谢谢。

【问题讨论】:

    标签: c++ stl


    【解决方案1】:

    您可以使用find_if,它允许您提供一个检查相等值的函数。

    auto check_something = 
         [&something](const list<*A>::iterator& iter){return *iter == something; };
    
    find_if(list.begin(),list.end(),check_something)
    

    【讨论】:

    • “auto”的语法是什么?
    • @Anton 是 C++11 的新特性之一。编译器通常知道右侧表达式(在本例中为 lambda)的返回类型是什么。由于您将其传递给模板函数,因此您不需要知道真实类型。在这种特殊情况下,check_something 将是 std::function&lt;bool(const list&lt;*A&gt;::iterator)&gt; 类型。如果你不能使用 C++11,另一种方法是编写一个结构来聚合一些东西并提供operator(const list&lt;*A&gt;::iterator&amp;) 与上面的 lambda 的内容。
    • 我可以在没有自动功能的情况下做到这一点吗?我的意思是,根据我作为输入获得的变量检查某些东西的功能?
    【解决方案2】:

    你可以使用

    if(**iter == something)
    

    如果你想取消引用指针。

    在C++1x中,也有

    for(auto ptr : list)
        if(*ptr == something)
    

    【讨论】:

    • 第一件事其实和我做的一样,c++1x是什么?还有另一种方法可以做我对 stl find func 所做的事情吗?
    • @Anton:“C++1x”是当前标准“C++11”的拼写错误。 (在两年前成为标准之前,它被非正式地称为“C++0x”,这可能就是“x”的来源)。
    • C++1x就是我们以前所说的C++14。
    • @bstamour:这被称为 C++1y,以(据说)避免混淆。这里的代码在 C++11 中很好。
    • @Mike,你是对的 - 我的错。是的,它是有效的 C++11 代码,我从未声明过。无论如何,1x 只是 1y 的 alpha 减少;-)
    【解决方案3】:

    没有什么说你不能创建一个全局非成员operator ==,它对指针或指针和对象的组合进行操作。如果你有很多类型,你可以为任何类型模板化指针与对象相等的组合。

    编辑以添加此提示:将比较与您的对象放在命名空间中,然后依赖于参数的查找将找到它,而无需将全局 T* == T 放在捕获所有内容的范围内:

    namespace equals {
        struct A {
            A(int x) :x(x) { }
            bool operator == (const A &other) const {
                return other.x == x;
            }
            int x;
        };
    
        template <typename T>
        bool operator == (const T *lhs, const T &rhs) {
            return *lhs == rhs;
        }
        template <typename T>
        bool operator == (const T &lhs, const T *rhs) {
            return lhs == *rhs;
        }
    }
    

    现在您可以执行以下操作:

    equals::A b(1), c(1);
    if (b == &c) std::cerr << "good!" << std::endl;
    

    【讨论】:

      【解决方案4】:

      您可以查看专为此目的设计的boost::indirect_iterator。

      find(
          boost::make_indirect_iterator( list.begin() ),
          boost::make_indirect_iterator( list.end() ),
          something );
      

      【讨论】:

      • 这是 c++ 中的新功能吗?
      • 不,Boost 是一个广泛使用的高质量库集合。它的许多部分已经成为(或至少激发了)标准化的 C++。然而,据我所知,标准库中目前没有像 indirect_iterator 这样的东西。
      • @Anton(忘记在之前的评论中标记你)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-11
      • 2016-04-02
      • 2012-02-20
      • 2014-06-15
      • 2014-12-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多