以下C ++程序有什么问题?

时间:2017-04-05 18:18:33

标签: c++ c++11

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

package GUI;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class MainWindow extends JFrame {

    private Container mainPane;

    private JButton mainButton;

    private JButton clientButton;

    private JButton residentialButton;

    private JButton commercialButton;

    private Vector<JPanel> panelList;

    public MainWindow() {
        panelList = new Vector<JPanel>(4);

        JPanel tempPanel = createMainPanel();
        panelList.add(tempPanel);

        ClientWindow clientWindow = new ClientWindow();
        panelList.add(clientWindow.createClientPanel());

        ResidentialWindow residentialWindow = new ResidentialWindow();
        panelList.add(residentialWindow.createResidentialPanel());

        CommercialWindow commercialWindow = new CommercialWindow();
        panelList.add(commercialWindow.createCommercialPanel());
    }

    public void createWindow() {
        this.setTitle("Management Software");
        int frameWidth = 936;
        int frameHeight = 592;
        double screenWidth = this.getToolkit().getScreenSize().getWidth();
        double screenHeight = this.getToolkit().getScreenSize().getHeight();
        int startX = (int) (screenWidth / 2 - frameWidth / 2);
        int startY = (int) (screenHeight / 2 - frameHeight / 2);
        this.setSize(frameWidth, frameHeight);
        this.setLocation(startX, startY);

        mainPane = this.getContentPane();
        mainPane.setLayout(new BorderLayout(5, 5));

        JPanel buttonPanel = new JPanel(new GridLayout(1, 4));
        Border buttonEdge = BorderFactory.createRaisedBevelBorder();

        mainButton = new JButton("Main");
        mainButton.setBorder(buttonEdge);
        mainButton.addActionListener(new ButtonListener());
        buttonPanel.add(mainButton);

        clientButton = new JButton("Client");
        clientButton.setBorder(buttonEdge);
        clientButton.addActionListener(new ButtonListener());
        buttonPanel.add(clientButton);

        residentialButton = new JButton("Residential");
        residentialButton.setBorder(buttonEdge);
        residentialButton.addActionListener(new ButtonListener());
        buttonPanel.add(residentialButton);

        commercialButton = new JButton("Commercial");
        commercialButton.setBorder(buttonEdge);
        commercialButton.addActionListener(new ButtonListener());
        buttonPanel.add(commercialButton);

        mainPane.add(buttonPanel, BorderLayout.NORTH);
        mainPane.add(panelList.get(0), BorderLayout.CENTER);

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    private JPanel createMainPanel() {
        JPanel mainPanel = new JPanel();
        JLabel mainL = new JLabel("The Main Screen",SwingConstants.CENTER);
        mainL.setForeground(Color.blue);
        mainL.setFont(new Font("Copperplate Gothic Bold",Font.BOLD,48));
        mainPanel.add(mainL);
        return mainPanel;
    }

    /***************************** INNER CLASSES *****************************/

            private JPanel  tp;

            @Override
            public void actionPerformed(ActionEvent e){
                for(int i = 0; i < panelList.size(); i++){
                    tp = panelList.get(i);
                    mainPane.remove(tp);
                    tp.setVisible(false);
                }

                if(e.getSource() == mainButton){
                    tp = panelList.get(0);
                    mainPane.add(tp,BorderLayout.CENTER);
                    tp.setVisible(true);

                }

                if(e.getSource() == clientButton){
                    tp = panelList.get(1);
                    mainPane.add(tp,BorderLayout.CENTER);
                    tp.setVisible(true);

                }
                if(e.getSource() == residentialButton){
                    tp = panelList.get(2);
                    mainPane.add(tp,BorderLayout.CENTER);
                    tp.setVisible(true);

                }
                if(e.getSource() == commercialButton){
                    tp = panelList.get(3);
                    mainPane.add(tp,BorderLayout.CENTER);
                    tp.setVisible(true);
                    }
                }
            }
    }

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

#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(),即空实现。但是我仍然没有获得所需的输出,似乎root,leaf1和leaf2都是调用树而不是它们各自的inorders。

5 个答案:

答案 0 :(得分:3)

您从未实施过05/04/2017

tree::inorder

在这里你声称有这样的功能 - 它的实现在哪里?

此外,这没有意义:

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

您将tree leaf1 = non_emp_tree(1, emp_tree(), emp_tree()); 的值设置为等于tree的值。这肯定不会有用。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

#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();
}

使用clang编译,生成1 2 3

答案 3 :(得分:1)

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

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

然而,这很快就会导致一系列其他问题,因为你正在左右切割你的对象!

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

此代码不可能具有您想要的效果。 non_emp_tree包含tree对象无法存储空间的成员变量。即使它确实如此,您也无法保证对象的行为符合您的预期。在inorderleaf1的调用会尝试调用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,但这需要对代码进行一些重大的重构。

答案 4 :(得分:0)

&#34; inorder&#34;类&#34;树的方法&#34;未实现,因此在调用它时会得到对此方法的未定义引用。