【问题标题】:C++. Object is instantiated with wrong constructor?C++。对象是用错误的构造函数实例化的?
【发布时间】:2013-12-18 19:29:57
【问题描述】:

我收到一个奇怪的错误,关于我什至没有调用的函数没有匹配的函数。这是错误:

BinarySearchTree.h:18:45: error: no matching function for call to ‘BinaryTree<int>::BinaryTree()’ BinarySearchTree<T>::BinarySearchTree(T elem)

显然它没有找到该功能,因为我没有它。我没有它,因为实例化一个完全空的二叉树是毫无意义的(或者至少在我看来是这样)。我也意识到那里有包含这些数据结构的库。我这样做只是为了帮助学习我的数据结构课程中的材料以及了解更多关于 C++ 的信息,直到最近我才将其用作“C with classes”。我不明白为什么编译器会要求我提供那个构造函数,如果我不想把它放在里面。

这是源文件。我没有使用默认构造函数来实例化树,这让我非常困惑。此外,preorder 方法在基类中完美运行,因此它应该与派生类一起使用(我只是创建派生类来添加特定于二叉搜索树的方法,但它仍然是二叉树)。

#include "../headers/BinarySearchTree.h"
#include <cstdio>

void print_int_node(BTreeNode<int>* tgt)
{
    printf("%d, ", tgt->getElement());
}

int main(int argc, char* argv[])
{
    BinarySearchTree<int> myTree(5);

    printf("Pre-order: \n");
    myTree.preorder(myTree.root, print_int_node);
    printf("\n");

    return 0;
}

这是我正在使用的类:

BinarySearchTree.h:

#ifndef _BINARY_SEARCH_TREE_H_
#define _BINARY_SEARCH_TREE_H_

#include "BinaryTree.h"

template <typename T>
class BinarySearchTree : public BinaryTree<T> {
    void _add(BTreeNode<T>*, T elem);

    public:
        BinarySearchTree(T);

        void add(T);
};

template <typename T>
BinarySearchTree<T>::BinarySearchTree(T elem)
{
    this->root = new BTreeNode<T>(elem);
}

template <typename T>
void BinarySearchTree<T>::add(T elem)
{

}

/***PRIVATE HELPER FUNCTIONS***/
template <typename T>
void BinarySearchTree<T>::_add(BTreeNode<T>* n, T elem)
{
    if(elem >= n->getElement()){
        if(n->getRightChild() != NULL){
            _add(n->getRightChild(), elem);
        }else{
            n->setRightChild(new BTreeNode<T>(elem));
        }
    }else{
        if(n->getLeftChild() != NULL){
            _add(n->getLeftChild(), elem);
        }else{
            n->setLeftChild(new BTreeNode<T>(elem));
        }
    }
}

#endif //_BINARY_SEARCH_TREE_H_

BinaryTree.h:

#ifndef _BINARY_TREE_H_
#define _BINARY_TREE_H_

#include "BTreeNode.h"

template <typename T>
class BinaryTree {
    public:
        BTreeNode<T>* root;

        BinaryTree(T);

        //traversals
        void preorder(BTreeNode<T>*, void (*func)(BTreeNode<T>*));
        void inorder(BTreeNode<T>*, void (*func)(BTreeNode<T>*));
        void postorder(BTreeNode<T>*, void (*func)(BTreeNode<T>*));
};

template <typename T>
BinaryTree<T>::BinaryTree(T elem)
{
    root = new BTreeNode<T>(elem);
}

template <typename T>
void BinaryTree<T>::preorder(BTreeNode<T>* node, void (*func)(BTreeNode<T>*))
{
    if(node == NULL)
        return;

    func(node);
    preorder(node->getLeftChild(), func);
    preorder(node->getRightChild(), func);
}

template <typename T>
void BinaryTree<T>::inorder(BTreeNode<T>* node, void (*func)(BTreeNode<T>*))
{
    if(node == NULL)
        return;

    inorder(node->getLeftChild(), func);
    func(node);
    inorder(node->getRightChild(), func);
}

template <typename T>
void BinaryTree<T>::postorder(BTreeNode<T>* node, void (*func)(BTreeNode<T>*))
{
    if(node == NULL)
        return;

    postorder(node->getLeftChild(), func);
    postorder(node->getRightChild(), func);
    func(node);
}
#endif //_BINARY_TREE_H_

BTreeNode.h:

#ifndef _B_TREE_NODE_H_
#define _B_TREE_NODE_H_

#define NULL 0

template <typename T>
class BTreeNode {
    T element;
    BTreeNode<T>* left;
    BTreeNode<T>* right;

    public:
        BTreeNode(T);
        BTreeNode(T, BTreeNode<T>*, BTreeNode<T>*);
        ~BTreeNode();

        T getElement();
        BTreeNode<T>* getLeftChild();
        BTreeNode<T>* getRightChild();

        void setElement(T elem);
        BTreeNode<T>* setLeftChild(BTreeNode<T>*);
        BTreeNode<T>* setRightChild(BTreeNode<T>*);
};

template <typename T>
BTreeNode<T>::BTreeNode(T elem)
{
    element = elem;
    left = NULL;
    right = NULL;
}

template <typename T>
BTreeNode<T>::BTreeNode(T elem, BTreeNode<T>* l, BTreeNode<T>* r)
{
    element = elem;
    left = l;
    right = r;
}

template <typename T>
BTreeNode<T>::~BTreeNode<T>()
{
    left = NULL;
    right = NULL;
}

template <typename T>
T BTreeNode<T>::getElement()
{
    return element;
}

template <typename T>
BTreeNode<T>* BTreeNode<T>::getLeftChild()
{
    return left;
}

template <typename T>
BTreeNode<T>* BTreeNode<T>::getRightChild()
{
    return right;
}

template <typename T>
void BTreeNode<T>::setElement(T elem)
{
    element = elem;
}

template <typename T>
BTreeNode<T>* BTreeNode<T>::setLeftChild(BTreeNode<T>* l)
{
    left = l;
    return left;
}

template <typename T>
BTreeNode<T>* BTreeNode<T>::setRightChild(BTreeNode<T>* r)
{
    right = r;
    return right;
}
#endif //_B_TREE_NODE_H_

【问题讨论】:

  • 这不是问题,但是以下划线开头后跟大写字母(_BINARY_SEARCH_TREE_H__BINARY_TREE_H__B_TREE_NODE_H_)的名称保留给实现(编译器及其标题)。不要使用它们。
  • #define NULL 0 放在任何地方都是一件可怕的事情,尤其是标题。 NULL 已经是许多标准头文件中的宏。

标签: c++ class inheritance constructor


【解决方案1】:

其实,你在叫它。

BinarySearchTree 上的构造函数中:

template <typename T>
BinarySearchTree<T>::BinarySearchTree(T elem)
{
    this->root = new BTreeNode<T>(elem);
}

您没有显式调用父类的构造函数,因此它使用默认值。你需要做这样的事情:

template <typename T>
BinarySearchTree<T>::BinarySearchTree(T elem) : BinaryTree(elem)
{
    this->root = new BTreeNode<T>(elem);
}

使用你的初始化列表!

附带说明一下,这也会导致内存泄漏,因为两个构造函数都使用自己的 new BTreeNode... 副本初始化成员 root

您还应该阅读构造函数在继承情况下的工作方式。

【讨论】:

  • 两者都可以。
  • 如果我只实例化一个对象,为什么会有两次初始化?
  • 你继承自 BinaryTreeBinarySearchTree。两个构造函数都被调用。
  • @Hugo 继承树中的所有构造函数都是自上而下调用的。析构函数都是自下而上调用的。
  • 哦,没错。那么我想保持两个指向根的指针不被创建的方法是只使用从基类继承的构造函数?
【解决方案2】:

类 BinaryTree 没有从 BinarySearchTree 的构造函数调用的默认构造函数,因为 BinaryTree 是 BinarySearchTree 的基类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-05
    • 2015-03-25
    • 2014-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多