C++:为什么这个sync()在这个Composition模式中不起作用?

rom*_*ovs 4 c++ algorithm composition

我正在尝试通过使用看起来像组合模式的东西来构建一个可以具有任意数量的子进程条的进度条类.

假设我有这个课程pbar:

class pbar
{
    public:
        pbar(const int w) { width = w; } // already sets the
        ~pbar() {}

         void setwidth(const int w) { width = w; } // set the width to w
         void show() const;
         void sync();

         void add(const pbar bar)
         {
              // add's a subbar
              subbars.pushback(bar);
         }

     private:
         std::vector<pbar> subbars; // the sub-process progressbars
         int width;                 // onscreen width of the pbar
};
Run Code Online (Sandbox Code Playgroud)

如您所见,它pbar有两个成员:宽度和子进程条(它们本身pbars).我一直在尝试实现一个sync函数,它改变了pbarsin的所有宽度,subbars以匹配pbar它的调用:

void pbar::sync()
{
    for ( pbar bar : subbars )
    {
         bar.setwidth(width);  // first set the width of the subbar
         bar.sync();           // secondly make it sync up it's subbars
    }
}
Run Code Online (Sandbox Code Playgroud)

但这似乎不起作用.我尝试过使用这个测试程序:

int main()
{
    pbar a(1);
    pbar b(2);
    pbar c(3);
    pbar d(4);

    c.add(d);
    b.add(c);
    a.add(b);

    a.show();
    std::cout << "syncing" << std::endl;
    a.sync();
    a.show();
}
Run Code Online (Sandbox Code Playgroud)

show函数定义为:

void pbar::show() const
{
    std::cout << w << std::endl;
    for ( pbar bar : subbars )
    {
         bar.show();
    }
}
Run Code Online (Sandbox Code Playgroud)

预期的产出是:

1
1
1
1
Run Code Online (Sandbox Code Playgroud)

但它是:

1
2
3
4
Run Code Online (Sandbox Code Playgroud)

奇怪,这是该show()函数不正确地遍历到所有的subbars,但它看起来像sync()没有(其实,用cout我申明,在实际,但它似乎没有任何效果).

我的代码出了什么问题?它不是使用c++0xfor循环类型,因为我尝试使用较旧的迭代器循环.我找不到我犯的错误.我认为这事做的事实,我改变了错误的pbar使用当s setwidthsync.

免责声明:这实际上是一个较大项目的一部分,而且这个类比这里显示的要复杂得多,但是我设法使用上面的代码重现了不需要的行为(顺便说一句,它不是复制粘贴的,可能包含错字的)

Blc*_*ght 5

您遇到的问题是您在sync()方法的循环中使用了局部变量"bar".这是制作每个子栏的副本,并操纵副本而不是原始版本(保留在向量中).这就是为什么在以后调用show()方法时没有看到更改"粘贴"的原因.

您可以通过使用引用而不是常规变量来解决此问题.尝试:

for ( pbar &bar : subbars )
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

您可能希望在addSubBar()方法中进行类似的更改,因为您还要在向量中保存另一个副本之前复制您传入的值.您可以通过将其参数作为参考来跳过一个副本.避免使用第二个副本需要更多的小心处理内存(我将留下另一个问题).