【问题标题】:C++: Iterating through objects to call the same methodC ++:遍历对象以调用相同的方法
【发布时间】:2012-04-15 05:19:46
【问题描述】:

在 C++ 中,假设您有一大堆对象要调用相同的方法。

Alice->callSameMethod();
Bob->callSameMethod();
...
Yoyo->callSameMethod();

但是从 Alice 到 Yoyo 输入同一行很麻烦。有没有办法做类似的事情:

For (each x in {Alice,Bob, ..., Yoyo}) x->callSameMethod;

我在这里看到了 for_each:http://www.cplusplus.com/reference/algorithm/for_each/ 但是没看懂。

【问题讨论】:

  • 这些对象是在数组还是标准库容器中?
  • 它们是同一类型还是基本类型?
  • 再说一遍:如果不是,您应该制作它们。
  • 谢谢。每个人的好答案。不过,我仍然更喜欢在 python 中完成迭代的方式;更加直接和直观。

标签: c++ oop object foreach iteration


【解决方案1】:

例子:

class Base{public: virtual int callSameMethod() = 0;};
           //pure virtual, can make it a default implementation
class Alice: public Base {public: int callSameMethod();...}; // own implementation
class Bob: public Base {public: int callSameMethod();...}; // own implementation
class YoYo: public Base{public: int callSameMethod();...}; // own implementation

代码中的某处:

Base* p1 = new Alice();
Base* p2 = new Bob();

std::vector<Base*> v;
std::vector<Base*>::iterator it;
v.push_back(p1);
v.push_back(p2);
for (it = v.begin(); it != v.end(); it++) (*it)->callSameMethod();

这称为“多态性”,您的基类定义了公共接口,您可以通过该接口调用任何派生类,而无需知道它们究竟是哪种派生类。您可以使用std::for_each 代替简单的循环,或者使用vector 进行索引访问而不是迭代器,无论您喜欢什么。

【讨论】:

    【解决方案2】:

    所有对象都必须有一个共同的基本类型或属于同一类型。

    class Base { public: virtual void callSameMethod() = 0; }; // abstract base
    class Derived1 : public Base { public: virtual void callSameMethod() {:::}; };
    class Derived2 : public Base { public: virtual void callSameMethod() {:::}; };
    
    // instances
    Base* Alice = new Derived1;
    Base* Bob   = new Derived2;
    Base* YoYo  = new Derived1;
    

    如果你有这个,最优雅的解决方案取决于你的 C++ 版本。

    C++03中,您可以创建一个包含指向所有元素的指针的容器

    Base* const list[] = {Alice, Bob, YoYo};
    

    并使用普通的 for 循环对其进行迭代

    int length = (sizeof(list) / sizeof(Base*));
    for(int i = 0; i < length; ++i) list[i]->callSameMethod();
    

    或 std::for_each

    #include <algorithm>
    #include <functional>
    
    std::for_each(list, list + length, std::mem_fun(&Base::callSameMethod));
    

    在这种情况下,我不鼓励使用 std::vector。矢量迫使您使用过于冗长的语法进行初始化和迭代,并且速度也会慢得多。

    如果您有一个支持 C++11 的编译器,但是有一个更简单的解决方案:

    #include <initializer_list>
    
    for (auto i : {Alice, Bob, YoYo}) i->callSameMethod();
    

    请注意,初始化列表中的所有元素都必须是相同的指针类型,Base*。如果不是这种情况,则必须明确说明初始化列表的类型:

    // alternative declarations with different pointer types
    Derived1* Alice = new Derived1;
    Derived2* Bob   = new Derived2;
    Derived1* YoYo  = new Derived1;
    
    auto objects = std::initializer_list<Base*>{Alice, Bob, YoYo};
    for (auto i : objects) i->callSameMethod();
    

    【讨论】:

      【解决方案3】:

      您需要所有持有“callSameMethod()”的对象都继承同一个接口,其中“callSameMethod()”是一个虚函数。所以你可以使用“for_each”来做你想做的事。顺便说一句,你也需要一个仿函数。

      【讨论】:

        【解决方案4】:

        如果它们是多态的,这种事情就可以做到。如果它们都继承自同一个类(如果它们都有共同的方法,它们可能应该继承),那么您可以将它们全部存储在基类类型指针的std::vector 中。然后就是简单的遍历vector,调用这个方法。

        for ( std::vector<BaseClass*>::iterator it = objectsVec.begin(); 
                                                it != objectsVec.end();
                                                ++it )
        {
            (*it)->callSameMethod();
        }
        

        【讨论】:

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