在A類中,有一個向量V. V是一個私人成員。如何從C++中的其他類迭代獲取數據?
在B班,我想打印V. 的所有項目要做到這一點,最好的方法是什麼?
在同一個類中獲得一個向量的迭代器很容易,但在另一個類中卻不容易。
謝謝您的閱讀。
在A類中,有一個向量V. V是一個私人成員。如何從C++中的其他類迭代獲取數據?
在B班,我想打印V. 的所有項目要做到這一點,最好的方法是什麼?
在同一個類中獲得一個向量的迭代器很容易,但在另一個類中卻不容易。
謝謝您的閱讀。
我擁有這個向量,最高可以打印出來。儘可能少地展示,尤其是私人會員。
另一種方法是訪問者模式;這樣可以保持數據封裝,但卻具有很大的靈活性。
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);
}
};
如果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, " "));
}
}
如果這是真的,'A'必須有一個方法來處理每個可以用矢量數據執行的操作。我強烈反對。 – sbi 2009-09-02 13:14:49
@sbi:你不知道這個問題,你的評論是誠實的虛假,因爲替代方案將暴露矢量。以* any *形式公開矢量只有在對其執行多個操作時纔有意義(如您所述)。另一方面,我的代碼隱藏了不必要的細節,同時公開了請求的界面。我同意它不應該過於具體,以免妨礙重用。但考慮到這個問題的稀缺信息,*我們*在這裏無法做出決定。我的代碼是一個完全有效的外觀用例。 – 2009-09-02 13:27:10
@Konrad:Wilka和xtofl都找到了不暴露向量的解決方案(我不計算typedef'd迭代器,因爲這隻需要重新編譯,可以通過使用pimpl'd迭代器來繞過)在'A'中執行特定的操作。我發現兩種解決方案都比你的更好。那可能就是我,但那就是我。 ':)' – sbi 2009-09-02 13:51:46
不知道有關的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;
}
}
}
返回對內部數據的直接引用可能是我能想象到的最糟糕的想法。現在,每個人都依賴於'B'具有'std :: vector
可能,但它直接回答這個問題。 – 2009-09-02 19:05:04
如果V是一個私人成員,那麼你不得不問,你爲什麼想從課堂以外到達它?爲了避免違反這一數據的封裝,你有幾種選擇:
例如:
A::printInternalData(const B& printer) { printer.print(V); };
除此之外,您必須將V暴露於外界。
那麼如何實現this_stuff_begin()
和this_stuff_end()
成員爲矢量返回迭代器?目前還不清楚有什麼用有它雖然私人的......
以你的觀點:
這是很容易獲得的 在同一類的向量迭代器,但不 容易另一類。
(並假設想要打印的元素是一個公正的其他一些複雜動作的佔位符)
,您仍然可以暴露的迭代器從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
代替,如果您需要寫入權限(儘管這可能是一個糟糕的設計選擇,寫信給這樣的內部成員)。
這實際上並不是訪客模式的一個例子(訪客實現了雙重調度),但它仍然是很好的代碼。 – 2009-09-02 12:14:29
它的確不是直接的O-O版本。它反映了所謂的「內部」訪問者。你可以同時提供一個功能或一個對象作爲訪問者。 'visit'函數用'operator()'代表' – xtofl 2009-09-02 12:32:48
我不同意_「如果'A'擁有這個向量,則由'A'來打印它。如果是這樣,'std :: vector'(擁有它的數據)將不得不具有打印功能。我非常喜歡你的替代解決方案。但是,請注意,目前(IIRC,這在C++ 1x中發生了變化),不允許使用函數本地類型作爲模板參數。 – sbi 2009-09-02 13:13:50