2016-04-23 3 views
0
template<class KeyType, class ValueType, class Hash = std::hash<KeyType> > 
class HashMap { 
public: 
    Hash hasher; 

    HashMap(Hash override_ = hasher) { 
     hasher = override_; 
    } 
}; 

Hier ist mein Code. Was ich erwarte, ist, dass ich den Standardwert für hasher beibehalte, wenn keiner vom Konstruktor geliefert wurde, oder ändere es andernfalls in new. Was ich bekomme ist das: invalid use of non-static data member 'hasher'. Ich habe bereits gedacht, dass ich hasher durch Hash() als Standardwert ersetzen kann; aber was, wenn ich kein Standard Hash Objekt, aber etwas komplizierter benötigt? Und warum hat mein erster Versuch nicht kompiliert?Warum kann ich den Klassenkonstruktorparameter nicht auf einen Standardwert setzen?

+0

Standard Argumente für den Konstruktor gelöst werden, bevor das Objekt Bau beginnt, so 'hasher' zu diesem Zeitpunkt nicht –

+0

A existieren würde eine gute Lösung wäre 2 Konstruktoren, die andere wäre 'HashMap() {}' –

Antwort

2

Sie versuchen, als Standardwert für Konstruktorparameter ein Mitglied einer Klasse zu verwenden, während das Objekt noch nicht erstellt wurde. Das kann nicht funktionieren, wenn das Mitglied nicht statisch ist. Um zu tun, was Sie wollen, können Sie 2 Konstruktoren auf diese Weise definieren:

#include <map> 
template<class KeyType, class ValueType, class Hash = std::hash<KeyType> > 
class HashMap { 
public: 
    Hash hasher; 

    HashMap(Hash override_) { 
     hasher = override_; 
    } 
    HashMap() { 
    } 
}; 
+0

Was ich nicht verstehe, ist _why_ Ich kann es nicht so verwenden. Ich habe dieses Problem bereits umgangen, indem ich 'Hash()' als Standardwert verwendet habe, also geht es bei meiner Frage mehr um "Warum?" als über "Wie?". – Akiiino

+0

@Akiiino 'hasher' ist noch nicht an diesem Punkt erstellt, wie werden Sie es verwenden? – Slava

+0

@Slava aber was wäre, wenn es "statisch" wäre - wenn ich zuerst 'HashMap' erstelle, ist es noch nicht erstellt, oder? – Akiiino

0

Es ist wie Standards verboten. Dies wird in Abschnitt 8.3.6 des C++ 03-Standards beschrieben. Es ist im Grunde jeder Ausdruck, der nicht von irgendetwas im lokalen Gültigkeitsbereich abhängt, so dass jeder Ausdruck, der von lokalen Variablen, Parametern einer Funktion oder von "diesem" abhängt, ausgeschlossen ist.

0

Nun, was Sie tun können, ist dies:

template<class KeyType, class ValueType, class Hash = std::hash<KeyType> > 
class HashMap { 
public: 
    Hash hasher; 

    HashMap(Hash override_ = {}) : hasher{std::move(override_)} {} 
}; 

Wenn keine angegeben, wird der Standard Konstruktor aufgerufen.

Ich persönlich denke, die beste Option, um einen Standard-Konstruktor hinzuzufügen wäre:

template<class KeyType, class ValueType, class Hash = std::hash<KeyType> > 
class HashMap { 
public: 
    Hash hasher; 

    HashMap() = default; 
    HashMap(Hash override_) : hasher{std::move(override_)} {} 
};