2012-05-01 6 views
1

バイナリ検索ツリークラスを実装しようとしていますが、コンパイラがエラーを投げています。コンパイラは、呼び出しに一致する関数がないことを示しています(プロトタイプに1つあります)

template <class Item, class Key> 
class bstNode 
{ 
public: 
    bstNode(); 
    bstNode(const Item& init_data, const Key& init_key, bstNode<Item, Key> *init_left, bstNode<Item, Key> *init_right); 
    ~bstNode(); 
    bstNode<Item, Key>* tree_copy(const bstNode<Item, Key>*& root); 
private: 
    Item data; 
    Key key; 
    bstNode* left; 
    bstNode* right; 
}; 

    template <class Item, class Key> 
    //line 83 in the original code is below 
bstNode<Item, Key>* bstNode<Item, Key>::tree_copy(const bstNode<Item, Key>*& root) 
{ 
    bstNode<Item, Key>* l_ptr; 
    bstNode<Item, Key>* r_ptr; 
    if (root == NULL) return NULL; 
    l_ptr = tree_copy(root -> left()); 
    r_ptr = tree_copy(root -> right()); 
    return new bstNode<Item, Key> (root -> data(), l_ptr, r_ptr); 
} 

.hファイルが空の主な機能と罰金コンパイルが、私はbstNode.cxxで次のコードビットでそれをしようとすると、それがエラーを与えて、クラッシュ:bstNode.hファイルはこちらです。

#include <cstddef> 
#include <algorithm> 
#include <math.h> 
#include <iostream> 
#include "bstNode.h" 

using namespace std; 

int main() 
{ 
    bstNode<int, size_t>* root_ptr = NULL; 
    bstNode<int, size_t>* copy_root_ptr = root_ptr -> tree_copy(root_ptr); 
    return 0; 
} 

し、エラーがある:コードがある

bstNode.cxx: In function ‘int main()’: 
bstNode.cxx:14: error: no matching function for call to ‘bstNode<int, long unsigned int>::tree_copy(bstNode<int, long unsigned int>*&)’ 
bstNode.h:83: note: candidates are: bstNode<Item, Key>* bstNode<Item, Key>::tree_copy(const bstNode<Item, Key>*&) [with Item = int, Key = long unsigned int] 

プロトタイプは、関数の実装と全く同じである、サンセリフbstNode ::ので、私は何が起こっているのかわかりません。私はg ++コンパイラを使用しています。何か案は?ありがとう、ありがとう。

EDIT:問題を強調表示するためにコードを縮小しました。

+1

問題を切り分けることができれば、(あなたも)助けになります。エラーを示している最小の完全なプログラムにプログラムを縮小してください。 http://sscce.org/。 –

+0

[非ポインタへのポインタへのポインタからポインタへのポインタへの変換はなぜ合法ではないのですか?](http://stackoverflow.com/questions/2220916/why-isnt-それを法律に変換するポインタからポインタへの非ポインタへの変換)ポインターへの参照としても有効です。 –

答えて

6

コンパイラは(ほとんどの場合のように)コードを拒否するのが正しいです。問題は、T*&からconst T*&への変換がないため、既存の関数を使用できないことです。

変換が存在しないのはなぜですか?

その変換が存在しない理由は、const-correctnessを破るためです。この例で考えてみましょう:あなたが関数に渡されたポインタを変更する必要がないので、可能な解決策、今

const int k = 10; 
void f(const int*& kp) { 
    kp = &k;     // Fine, the pointer promises not to change the object 
} 
int main() { 
    int *p; 
    f(p);     // Does not compile, but assume it would 
          // after the call, p points to k 
    *p = 20;    // Modifying a constant!!!! 
          // p never promised not to change the pointee 
} 

は署名にさらに多くのconst秒を追加することですやって

bstNode<Item, Key>* tree_copy(const bstNode<Item, Key>* const & root); 

したがって、上記の例の問題であるポインタの変更をコードからブロックしています。しかし、あなたが本当にそれについて考えるならば、

なぜ最初にポインタへの参照を渡すのですか?

ポインタがそうconst&によってそれらを渡すことはあまり意味がありません、コピーして安価であり、そしてあなたが渡しているポインタを変更する機能を必要としないので、値渡しすることは、潜在的に正しいの両方になりますもっと効率的。

+0

それだけです!どうもありがとうございました。 – vanchagreen

+0

残念ながら私は先生の定義を変更できません。また、関数自体をconstにすることなくconst T *&を関数に渡すことはできませんが、定義を変更することはできません。何かアドバイス? – vanchagreen

6

プロトタイプは全く同じではありません。constの違いがあるためです。あなたはそれが非constポインタへの参照を取得しています

bstNode<int, size_t>* root_ptr; 
tree_copy(root_ptr); 

としてそれを呼んでいるのに対し、宣言は

bstNode<Item, Key>* tree_copy(const bstNode<Item, Key>*& root); 

(のconstポインタを参照)です。 foo *const foo *とするものに渡すことができますが、const foo * &というものを参考にしてfoo *を渡すことはできません。

+0

ああ、ありがとう、それはそれでなければならない。私はちょうど参照を取るだろうと思う。先生がそれを望んでいたので、それは不必要です。彼が私たちに割り当てを与えたとき、私は非常に混乱しました。なぜなら、constで修正できなかったなら、それを参照として渡すのは何だったのでしょうか?私はコンパイラが同意したと思う。 :D – vanchagreen

+0

@vanchagreen: 'const T *&'において、ポインタは* not * constであることに注意してください。ポインタは 'const T'へのポインタです。 'const T *&'は 'T const *&'と等価であり、 'T * const&'(*非const Tへのconstポインタへの参照ではありません*) –

+0

@DavidRodríguez-dribeas私はそれを知らなかった、ありがとう。 – vanchagreen

関連する問題