2009-09-02 56 views
1

在A类中,有一个向量V. V是一个私人成员。如何从C++中的其他类迭代获取数据?

在B班,我想打印V. 的所有项目要做到这一点,最好的方法是什么?

在同一个类中获得一个向量的迭代器很容易,但在另一个类中却不容易。

谢谢您的阅读。

回答

3

我拥有这个向量,最高可以打印出来。尽可能少地展示,尤其是私人会员。

另一种方法是访问者模式;这样可以保持数据封装,但却具有很大的灵活性。

struct A { 
    template< typename F > void each(F& f) const { 
    std::for_each(data.begin(), data.end(), f); 
    } 

private: 
    std::vector<int> data; 
}; 

struct B : public A { 
    static void tprint()(int i) { std::cout<<i<<std::endl; } 
    void print()const { 
    each(tprint); 
    } 
}; 
+0

这实际上并不是访客模式的一个例子(访客实现了双重调度),但它仍然是很好的代码。 – 2009-09-02 12:14:29

+0

它的确不是直接的O-O版本。它反映了所谓的“内部”访问者。你可以同时提供一个功能或一个对象作为访问者。 'visit'函数用'operator()'代表' – xtofl 2009-09-02 12:32:48

+1

我不同意_“如果'A'拥有这个向量,则由'A'来打印它。如果是这样,'std :: vector'(拥有它的数据)将不得不具有打印功能。我非常喜欢你的替代解决方案。但是,请注意,目前(IIRC,这在C++ 1x中发生了变化),不允许使用函数本地类型作为模板参数。 – sbi 2009-09-02 13:13:50

2

如果B要打印A的载体,这是对A的请求,所以A应该在其公共接口的方法来做到这一点,例如(说V具有类型vector<int>):

class A { 
… 
public: 
    void dump_values(std::ostream& out) const { 
     std::copy(V.begin(), V.end(), std::ostream_iterator<int>(out, " ")); 
    } 
} 
+1

如果这是真的,'A'必须有一个方法来处理每个可以用矢量数据执行的操作。我强烈反对。 – sbi 2009-09-02 13:14:49

+0

@sbi:你不知道这个问题,你的评论是诚实的虚假,因为替代方案将暴露矢量。以* any *形式公开矢量只有在对其执行多个操作时才有意义(如您所述)。另一方面,我的代码隐藏了不必要的细节,同时公开了请求的界面。我同意它不应该过于具体,以免妨碍重用。但考虑到这个问题的稀缺信息,*我们*在这里无法做出决定。我的代码是一个完全有效的外观用例。 – 2009-09-02 13:27:10

+0

@Konrad:Wilka和xtofl都找到了不暴露向量的解决方案(我不计算typedef'd迭代器,因为这只需要重新编译,可以通过使用pimpl'd迭代器来绕过)在'A'中执行特定的操作。我发现两种解决方案都比你的更好。那可能就是我,但那就是我。 ':)' – sbi 2009-09-02 13:51:46

-1

不知道有关的A类和B的责任,具体多少,我建议A类返回一个常量引用存储在B类矢量这给了你只读访问矢量,不需要复制的性能。

class B 
    { 
    private: 
     std::vector<int> m_vector; 
    public: 
     const std::vector<int>& GetVector() {return m_vector} 
    } 


    class A 
    { 
    private: 
     B m_b; 
    public: 
    void printVector() 
    { 
     const std::vector<int>& refToVec = m_b.GetVector(); 
     std::vector<int>::const_iterator iter = refToVec.begin(); 
     for (; iter != refToVec.end(); ++iter) 
     { 
      std::cout << *iter << std::endl; 
     } 
    } 
    } 
+0

返回对内部数据的直接引用可能是我能想象到的最糟糕的想法。现在,每个人都依赖于'B'具有'std :: vector '类型的对象'',它暴露在界面中。如果你测量并发现'std :: list '会更快,你将不得不根据'A'来更改所有的代码。 -1 – sbi 2009-09-02 13:09:28

+0

可能,但它直接回答这个问题。 – 2009-09-02 19:05:04

1

如果V是一个私人成员,那么你不得不问,你为什么想从课堂以外到达它?为了避免违反这一数据的封装,你有几种选择:

  1. 打印v的所有项目从A中
  2. 传递B的实例A,使得它可以用它来打印从V项目。

例如:

A::printInternalData(const B& printer) { printer.print(V); }; 

除此之外,您必须将V暴露于外界。

0

那么如何实现this_stuff_begin()this_stuff_end()成员为矢量返回迭代器?目前还不清楚有什么用有它虽然私人的......

5

以你的观点:

这是很容易获得的 在同一类的向量迭代器,但不 容易另一类。

(并假设想要打印的元素是一个公正的其他一些复杂动作的占位符)

,您仍然可以暴露的迭代器从A您的载体,可以的B内部使用通过typedef,例如

class A 
{ 
private: 
    std::vector<int> V; 
public: 
    typedef std::vector<int>::const_iterator const_iterator; 
    const const_iterator begin() const 
    { 
     return V.begin(); 
    } 

    const const_iterator end() const 
    { 
     return V.end(); 
    } 
}; 

然后你就可以使用这些迭代器是这样的:

class B 
{ 
public: 
    void Foo() 
    { 
     A a; 
     // do stuff that will put things into the collection inside 'a' 
     std::copy(a.begin(), a.end(), std::ostream_iterator<int>(std::cout, " ")); 
    } 
}; 

我在这种情况下使用const_iterator,因为你问只读访问,但可以使用iterator代替,如果您需要写入权限(尽管这可能是一个糟糕的设计选择,写信给这样的内部成员)。

+0

返回值上的顶级'const'是无稽之谈,但也没有任何害处。我认为这是一个非常好的答案。 +1 – sbi 2009-09-02 13:07:16

+0

谢谢Wilka。 – john6 2009-09-12 05:32:28