2009-09-02 71 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

相關問題