2016-11-23 3 views
1

Haben Sie Probleme zu verstehen, wie (und warum) diese Konvertierung nicht funktioniert.C++ - Vorlagen und Polymorphie keine brauchbare benutzerdefinierte Konvertierung

I haben Klasse A, Klasse B von der Klasse A abgeleitet ist, und der Klasse C von Klasse B. abgeleitet

class A {}; 
class B : public A {}; 
class C : public B {}; 

Ich möchte ein HashTable machen, die zwei Schablonen typenames <K, V> hat, wo der K a char und V ist eine binäre Suchbaum-Vorlagenklasse (BST<T>). Diese BSTs haben die Typen A, B und C.

template <typename K, typename V> 
class HashTable { 
public: 
    bool put(K key, V value); // adds key value pair to table 
private: 
    V* table; // table stores values 
    int size; // size of table 
}; 

template <typename T> 
class BST { 
public: 
    bool insert(T item); // adds item to tree 
private: 
    struct BSTNode {  // node structure 
     R data;    // item data 
     BSTNode *left;  // left child pointer 
     BSTNode *right;  // right child pointer 
    }; 
    BSTNode *root;   // pointer to root of tree 
}; 

Der folgende Code hat einen Fehler mit einem BST<C> in der Hash-Tabelle setzen, weil es nicht von BST<C> zu BST<A> umwandeln kann. Die letzte Zeile in main ist jedoch legal.

int main() { 
    HashTable<char, BST<A>> inventory; 
    BST<C> foo; 
    inventory.put('C', foo); 

    A *bar= new C(); 
} 

ich aber wegen Polymorphismus, BST<C> is-a BST<A>? Wie kann ich diesen Typunterschied umgehen, damit ich BST, BST und BST zu meinem hashmap hinzufügen kann?

Ich habe bereits versucht mit typedef in der Deklaration und das hat nicht funktioniert.

+0

Sieht so aus, als würden Sie 'A' in Ihrem benutzerdefinierten Container speichern, wodurch die Unterklasse entfernt wird. –

+0

Warten Sie ... was? Das ist der falsche Betrogene. Die damit verbundene Frage hat damit nichts zu tun. Stimme, um wieder zu öffnen. –

+0

@SamVarshavchik, total falsch dupe. – SergeyA

Antwort

1

Die Konvertierung kann nicht passieren. BST<C> kann nicht in eine BST<A> konvertiert werden, da es sich um völlig unterschiedliche, nicht verwandte Klassen handelt.

Wenn die Vorlage instanziiert wird, schaut es so (grossely):

template <> 
struct BST_C { 
    bool insert(C item); // adds item to tree 
    // ... 
}; 

template <> 
struct BST_A { 
    bool insert(A item); // adds item to tree 
    // ... 
}; 

Wie Sie sehen können, gibt es keine Beziehung zwischen den beiden.


Was können Sie dagegen tun?

Nun, Sie einen Konvertierungsoperator definieren könnte, beschränkt auf Basisklassen:

template <typename T> 
struct BST { 
    bool insert(T item); 

    // only enable for base classes ------------v 
    template<typename To, std::enable_if_t<std::is_base_of<To, T>>* = nullptr> 
    operator BST<To>() const { 
     // implement the conversion operator... 
    } 
}; 

Mit diesem Konvertierungsoperator, Ihre Klasse BST<C> ist umwandelbar in BST<B> und BST<A> sind.

+0

Dies löste den Syntaxfehler, und diese Erklärung macht den Typunterschied sehr deutlich, danke! Ich werde mehr über Konvertierungsoperatoren lesen müssen, um das Implementieren lernen zu können. –

0

Dies liegt daran, selbst wenn B eine mit A ist-eine Beziehung hat, BST<A>keine Beziehung mit BST<B> hat. Diese beiden Vorlageninstanzen stehen in keiner Weise miteinander in Beziehung und können sich sogar völlig voneinander unterscheiden.