1

二分探索木クラスを実装しようとしていますが、コンパイラがエラーをスローしています。bstNode.h ファイルは次のとおりです。

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 ファイルは、空の main 関数で正常にコンパイルされますが、bstNode.cxx の次のコードで試してみると、クラッシュしてエラーが発生します。コードは次のとおりです。

    #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++ コンパイラを使用しています。何か案は?ありがとうございます。

編集:問題を強調するためにコードを切り詰めました。

4

2 に答える 2

6

原型は全く同じではありませんconst。宣言は

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

(constポインタへの参照)一方、あなたはそれを

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

そのため、非定数ポインターへの参照を取得しています。また、 afoo *を取るものに a を渡すことはできますが、 a を取るものに参照const foo *渡しすることはできません。foo *const foo * &

于 2012-05-01T20:05:00.373 に答える
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関数に渡されたポインターを変更する必要がないため、可能な解決策は、署名にさらに s を追加することです。

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

そうすることで、コードがポインターを変更するのを妨げています。これが上記の例の問題です。でも、よくよく考えてみると、

そもそもポインタへの参照を渡すのはなぜですか?

ポインターは安価にコピーできるため、それらを渡すことconst&はあまり意味がありません。また、渡すポインターを関数で変更する必要がないため、値による受け渡しは正しくより効率的である可能性があります。

于 2012-05-01T20:05:45.420 に答える