遵循C++程序有什么问题

What is wrong with following C++ program?

本文关键字:什么 问题 程序 C++ 遵循      更新时间:2023-10-16

为什么下面的C++代码会给出下面提到的错误?另外,为什么这不是用C++编写递归数据结构的惯用方式?这种写C++的方式有什么根本性的问题吗?

#include<iostream>
using namespace std;

class tree{
public:
    virtual void inorder() {};
};
class emp_tree: public tree{
public:
    void inorder(){
    }
};
class non_emp_tree: public tree{
public:
    tree left, right;
    int val;
    non_emp_tree(int v, tree l, tree r): val(v), left(l), right(r) {};
    void inorder(){
        left.inorder();
        cout<<" "<<val<<" ";
        right.inorder();
    }
};


int main() {
    tree leaf1 = non_emp_tree(1, emp_tree(), emp_tree());
    tree leaf2 = non_emp_tree(3, emp_tree(), emp_tree());
    tree root = non_emp_tree(2, leaf1, leaf2);
    root.inorder();
    return 0;
}

编译器给出的错误:(我无法理解其中的大部分(

/tmp/ccAjhirw.o: In function `main':
b_t.cpp:(.text+0x16e): undefined reference to `tree::inorder()'
/tmp/ccAjhirw.o: In function `tree::tree()':
b_t.cpp:(.text._ZN4treeC2Ev[_ZN4treeC5Ev]+0x9): undefined reference to `vtable for tree'
/tmp/ccAjhirw.o: In function `tree::tree(tree const&)':
b_t.cpp:(.text._ZN4treeC2ERKS_[_ZN4treeC5ERKS_]+0xd): undefined reference to `vtable for tree'
/tmp/ccAjhirw.o: In function `non_emp_tree::inorder()':
b_t.cpp:(.text._ZN12non_emp_tree7inorderEv[_ZN12non_emp_tree7inorderEv]+0x19): undefined reference to `tree::inorder()'
b_t.cpp:(.text._ZN12non_emp_tree7inorderEv[_ZN12non_emp_tree7inorderEv]+0x56): undefined reference to `tree::inorder()'
/tmp/ccAjhirw.o: In function `tree::tree(tree&&)':
b_t.cpp:(.text._ZN4treeC2EOS_[_ZN4treeC5EOS_]+0xd): undefined reference to `vtable for tree'
/tmp/ccAjhirw.o:(.rodata._ZTI12non_emp_tree[_ZTI12non_emp_tree]+0x10): undefined reference to `typeinfo for tree'
/tmp/ccAjhirw.o:(.rodata._ZTI8emp_tree[_ZTI8emp_tree]+0x10): undefined reference to `typeinfo for tree'
collect2: error: ld returned 1 exit status

编辑:我将virtual void inroder()更改为virtual void inorder() {}即空实现。但是我仍然没有得到想要的输出,似乎根、叶 1 和叶 2 都在调用树的无序而不是它们各自的无序。

您从未实现过tree::inorder .

class tree{
public:
    virtual void inorder();
};

在这里,您声称有这样一个函数 - 它的实现在哪里?

此外,这没有意义:

tree leaf1 = non_emp_tree(1, emp_tree(), emp_tree());

您正在将tree的值设置为等于non_emp_tree的值。这当然不会做任何有用的事情。

virtual void inorder(){}应该在你的树类中,你缺少{}

首先,如果tree::inorder是一个抽象方法,你需要正确地声明它:

class tree{
public:
    virtual void inorder() = 0;
};

但是,这很快就会导致一堆其他问题,因为您正在左右切割对象!

tree leaf1 = non_emp_tree(1, emp_tree(), emp_tree());

此代码不可能产生您想要的效果。 non_emp_tree包含tree对象没有空间存储的成员变量。即使确实如此,您也无法保证对象的行为方式符合您的预期。在leaf1上调用inorder会尝试调用tree::inorder,而不是non_emp_tree::inorder,因为程序无法知道你打算在这里存储一个子类。

解决此问题的方法是对所有tree对象使用指针。

#include<iostream>
#include<memory>
class tree{
public:
    virtual void inorder() = 0;
    virtual ~tree() = default;
};
class emp_tree: public tree{
public:
    void inorder(){
    }
};
class non_emp_tree: public tree{
public:
    std::unique_ptr<tree> left, right;
    int val;
    non_emp_tree(int v, tree *l, tree *r): val(v), left(l), right(r) {};
    void inorder(){
        if(left) left->inorder();
        std::cout<<" "<<val<<" ";
        if(right) right->inorder();
    }
};
int main() {
    std::unique_ptr<tree> leaf1 = std::make_unique<non_emp_tree>(1, new emp_tree, new emp_tree);
    std::unique_ptr<tree> leaf2 = std::make_unique<non_emp_tree>(3, new emp_tree, new emp_tree);
    std::unique_ptr<tree> root = std::make_unique<non_emp_tree>(2, leaf1.release(), leaf2.release());
    root->inorder();
    return 0;
}

此代码的更好实现将完全避免使用裸new,但这需要对代码进行一些重大重构。

你可能试图做的是使用多态性。但是,为此,您必须使用指向基的引用或指针,而不是基本身。即

#include<iostream>
#include<memory>
struct tree
{
  virtual void inorder() = 0;  // abstract: cannot be called
  virtual ~tree() {}
};
struct emp_tree : tree
{
  void inorder() override
  {}
};
struct non_emp_tree : tree
{
  std::unique_ptr<tree> left,right; 
  int val;
  non_emp_tree(int v, tree*l, tree*r)
  : left(l), right(r), val(v) {}
  void inorder() override
  {
    left->inorder();
    std::cout<<" "<<val<<" ";
    right->inorder();
  }
};
int main() {
  auto leaf1 = new non_emp_tree(1, new emp_tree, new emp_tree);
  auto leaf2 = new non_emp_tree(3, new emp_tree, new emp_tree);
  auto root  = new non_emp_tree(2, leaf1, leaf2);
  root->inorder();
}

用叮叮当编译,产生1 2 3

类"tree"的"inorder"方法未实现,因此在调用此方法时会获得对此方法的未定义引用。