2016-05-12 77 views
-1

這裏是不編譯代碼:的std ::地圖和私有構造

#include <map> 
using namespace std; 

class A; 

class B { 
     friend class A; 
     int b; 
     B():b(1){}; 
     B(int b_):b(b_){}; 
}; 

class A { 
     map<int,B> objects; 
public: 
     void init(){ 
       objects[2]=B(3); 
     } 
}; 

int main(){ 
     A a; 
     a.init(); 
     return 0; 
} 

從我的錯誤信息理解:

/usr/include/c++/4.8/bits/stl_map.h: In instantiation of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = int; _Tp = B; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, B> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = B; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]’: 
foo.cc:18:24: required from here 
foo.cc:9:10: error: ‘B::B()’ is private 
      B():b(1){}; 
     ^
In file included from /usr/include/c++/4.8/map:61:0, 
       from foo.cc:1: 
/usr/include/c++/4.8/bits/stl_map.h:469:59: error: within this context 
      __i = insert(__i, value_type(__k, mapped_type())); 
                 ^

問題「地圖」不一個B的朋友,所以它可能不會使用構造函數B()(順帶一提,我注意到objects[2]=B(3);需要B()!)。

我發現了以下解決方法:

objects.insert(pair<int,B>(2,B(3))); 

其中工程...直到~B()也是私有的。

那麼,當B的構造函數和析構函數是私有的時候,有沒有辦法在A裏面建立一個B的地圖?

附加問題:爲什麼objects[2]=B(3);使用B()

+2

_「所以, ,當B的構造函數和析構函數是私有的時候,有沒有辦法在A中創建一個B的映射?「_ No. –

+0

」*根據我在錯誤消息*「什麼錯誤消息? – user2079303

+0

爲什麼downvote? –

回答

3

嚴格地說,這不是你的問題的答案,但我認爲它以更優雅的方式解決了你的問題。

而不是使B私人所有的字段,然後在一個朋友的關鍵字搞亂的,你可能會隱藏從外面的世界B級,通過使私人member class

#include <map> 

class A { 
    class B { 
     int b; 

     public: 
     B() : b(1){}; 
     B(int b_) : b(b_){}; 
     ~B() {} 
    }; 
    std::map<int, B> objects; 

    public: 
    void init() { 
     auto b = B(); 
     objects[2] = B(3); 
     objects.insert(std::pair<int, B>(2, B(3))); 
    } 
}; 

int main() { 
    A a; 
    A::B b; // 'A::B': cannot access private class declared in class 'A' 
    a.init(); 
    return 0; 
} 

這樣你仍然不能在A之外自由地構造B,但A可以以任何方式使用它。這也解開了B中更精細的封裝粒度:一些部分可以被私有/保護而不是A.它不是與朋友類代碼的情況。

示意性地,你可以把你的代碼爲:

A [ B [ private(a), private(b), private(c), ... ] ] 

雖然我的代碼更像是:

A[ private(B[a, b, c]) ] 

即的私有化是B的 「分解出來」

+0

這正是我需要的!我不知道私人會員課程。非常感謝。 –

1

看看這個鏈接http://www.cplusplus.com/reference/map/map/operator[]/,它說

這個函數的調用等效於:

(*((this->insert(make_pair(k,mapped_type()))).first)).second 

默認構造函數正在從類std::map'內調用這個範圍不是這個班的朋友。所以錯誤。

錯誤應該在那裏。這樣的構造函數不應該被聲明爲私有的。

解決此問題的另一種方法是將對象的構造委託給類A,並將整數映射到指向B的指針(或引用包裝器)。此映射只能通過接口訪問A曝光。這樣B對象的整個生命週期都由A管理,並且不會有不變量被破壞。

+1

感謝您的回答。我沒有討論錯誤的相關性,只是不理解爲什麼,並尋找解決方案:-) –

+1

@ L.Levrel我應該發佈一個解決方案,我認爲是體面的!我專注於其他事情,並沒有考慮到這一點。我會編輯我的答案 – Curious

+1

這是體面的。類Lisp引用(很多括號!)迫使我仔細檢查操作符[]是幹什麼的。所以這很有幫助。我接受了Drop的答案,這個答案解決了我的問題,但嚴格來說,它並沒有回答這個問題:請原諒我,作爲初學者,我沒有很好地表達我的問題。感謝您抽出寶貴時間來編輯您已經提出的答案,因爲我無法兩次贊成它,所以我會對您的評論贊不絕口:向您的2,000代表邁出一小步! (他們確實代表高調評論,對吧?) –