2013-03-03 13 views
5

Ich erstelle meine eigene benutzerdefinierte Filterklasse für Verwendung in boost :: filtered_graph. Das WeightMap-Konzept muss einen Standardkonstruktor, Kopierkonstruktor und Zuweisungsoperator haben.Zuweisen eines std :: shared_ptr in Zuweisungsoperatoren

Ich habe die Klasse erstellt, die ein privates Mitglied std :: shared_ptr hat. Meine Frage ist, wie ich den Zuweisungsoperator schreiben soll. Der Kopierkonstruktor war kein Problem, aber der Zuweisungsoperator funktioniert nicht.

class BFDMFilter 
{ 
private: 
const BGraph* m_battlemap; 
const std::shared_ptr<MoveAbility> m_mv_ab; 

public: 
BFDMFilter() : m_battlemap(nullptr), m_mv_ab() { } 
BFDMFilter(const BGraph* bmap, std::shared_ptr<MoveAbility> mv) : m_battlemap(bmap), m_mv_ab(mv) { } 

BFDMFilter(const BFDMFilter& filter) : m_battlemap(filter.m_battlemap), m_mv_ab(filter.m_mv_ab) { } 
BFDMFilter& operator=(const BFDMFilter& filter) 
{ 
    if(this != &filter) 
    { 
m_battlemap = filter.m_battlemap; 
m_mv_ab = filter.m_mv_ab; 
    } 

    return *this; 
} 

bool operator()(const Edge& edge) const 
{ 
    Tile::TileEdge path = (*m_battlemap)[edge]; 

    return m_mv_ab->CanMove(path.TerrainType()) > 0.0; 
} 

bool operator()(const Vertex& vertex) const 
{ 
    Tile tile = (*m_battlemap)[vertex]; 

    return m_mv_ab->CanMove(tile.TerrainType()) > 0.0; 
} 
}; 

Welche gibt mir dann einen Compiler-Fehler:

error: passing ‘const std::shared_ptr<momme::battle::MoveAbility>’ as ‘this’ argument of ‘std::shared_ptr<_Tp>& std::shared_ptr<_Tp>::operator=(std::shared_ptr<_Tp>&&) [with _Tp = momme::battle::MoveAbility, std::shared_ptr<_Tp> = std::shared_ptr<momme::battle::MoveAbility>]’ discards qualifiers [-fpermissive] 

Ich verstehe, warum; Der Zuweisungsoperator ändert die Referenzzählung von shared_ptr, wenn er die Zuweisung durchführt, so dass er verfolgen kann, wie viele offene Referenzen vorhanden sind. Aber wie schreibe ich dann den Zuweisungsoperator? std :: weak_ptr hat das gleiche Verhalten, und wenn ich den Verweis nicht-const, dann beschwert sich die Boost-Bibliothek, dass die Funktion gelöscht wird.

+2

Ich bin mir nicht sicher, warum Sie den Zeiger const sein müssen ... meinst du 'std :: shared_ptr m_mv_ab' stattdessen? Soll das 'std :: shared_ptr' selbst const oder das Objekt, auf das es zeigt, const sein? –

+1

Sie können keine Zuweisung mit * any * const Datenelement durchführen. Dies ist nicht spezifisch für 'shared_ptr'. – juanchopanza

Antwort

11

Es gibt keinen Grund, aus dem Code zu sein scheint m_mv_ab als

const std::shared_ptr<MoveAbility> m_mv_ab; 

zu erklären, die die Smart-Zeiger-Version ist:

MoveAbility * const m_mv_ab; 

(konstanter Zeiger auf nicht-Konstante MoveAbility)

Wenn das Objekt MoveAbility nicht geändert werden soll und es const sein soll, yo u tun sollten:

std::shared_ptr<const MoveAbility> m_mv_ab; 

, welche die Smart-Zeiger-Version ist:

const MoveAbility * m_mv_ab; 

(nicht konstanten Zeiger auf konstante MoveAbility)

Um dies etwas intuitiver Sie verwenden können, const als Suffix immer und immer von rechts nach links gelesen, außer dass std::shared_ptr<X> gelesen wird "(Smart) Zeiger auf X":

std::shared_ptr<MoveAbility> const m_mv_ab; // const ptr to non-const MoveAbility 
MoveAbility * const m_mv_ab; // const ptr to non-const MoveAbility 

std::shared_ptr<MoveAbility const> m_mv_ab; // non-const ptr to const MoveAbility 
MoveAbility const * m_mv_ab; // non-const ptr to const MoveAbility 

aber die meisten Leute verwenden const als Präfix wann immer möglich, was es verwirrend macht.

+1

Was für ein dummer Fehler; Ich kann nicht glauben, dass ich das vermisst habe. Danke, dass du es aufgezeigt hast. – Brad

+0

@Brad passiert die ganze Zeit, es ist nicht so intuitiv –

Verwandte Themen