【问题标题】:C++ how to solve class incomplete type when two class depends on each other当两个类相互依赖时,C ++如何解决类不完整类型
【发布时间】:2020-04-28 13:15:15
【问题描述】:

我现在正在学习设计模式,并阅读了《Ruminations on C++》一书。下面的例子是如何使用句柄类来做一些应用。

#include <iostream>
#include <string>
#include <utility>

using namespace std;

class Expr_node;
class Int_node;
class Unary_node;
class Binary_node;

class Expr {
  friend ostream& operator<<(ostream&, const Expr&);

  Expr_node* p;
 public:
  Expr(int);
  Expr(const string&, Expr);
  Expr(const string&, Expr, Expr);
  Expr(const Expr&);
  Expr& operator=(const Expr&);
};

Expr::Expr(int n) {
  p = new Int_node(n);
}

Expr::Expr(const string& op, Expr t) {
  p = new Unary_node(op, t);
}

Expr::Expr(const string & op, Expr left, Expr right) {
  p = new Binary_node(op, left, right);
}

class Expr_node {
    friend ostream& operator<< (ostream&, const Expr_node&);

protected:
    virtual void print(ostream&) const = 0;
    virtual ~Expr_node() { }
};

ostream& operator<< (ostream& o, const Expr_node& e) {
    e.print(o);
    return o;
}

class Int_node: public Expr_node {
  friend class Expr;

  int n;

  explicit Int_node(int k) : n(k) {}
  void print(ostream& o) const override { o << n;}
};

class Unary_node: public Expr_node {
  friend class Expr;
  string op;
  Expr opnd;
  Unary_node(const string& a, const Expr& b): op(a), opnd(b) {}
  void print(ostream& o) const override {o << "(" << op << *opnd << ")";}
};

class Binary_node: public Expr_node {
  friend class Expr;
  string op;
  Expr left;
  Expr right;
  Binary_node(const string& a, const Expr& b, const Expr& c): op(a), left(b), right(c) {}
  void print(ostream& o) const override { o << "(" << left << op << right << ")";}
};

在这个例子中,我想基于从Expr_node 类的继承来实现三种不同的操作。很明显,Int_node 在完整定义之前还没有得到很好的定义。我不知道如何解决这个问题。看来这本书有很多错误。

【问题讨论】:

  • “设计模式” ?不止一个,你在处理哪一个?
  • 您想了解更多关于forward declarations的信息。专业提示:在发布之前减少您的代码数量。没看过,太多了。
  • 只需移动Expr::Expr(int),使其位于Int_node的定义之后。
  • 您正在实施策略模式。朋友和前向声明是一团糟。寻找一个不同的例子。
  • @pasbi OP 在他们的代码中使用前向声明。

标签: c++ class handle


【解决方案1】:

回答这个问题(除了各种 cmets 中的其他注意事项):

你需要实现带有 int 参数的构造函数的定义

Expr::Expr(int n) {
  p = new Int_node(n);
}

在构造函数 Int_node(int n) 的定义之后,它在您的示例中内联在 Int_node 类的声明中:

class Int_node: public Expr_node {
  friend class Expr;

  int n;

  explicit Int_node(int k) : n(k) {}
  void print(ostream& o) const override { o << n;}
};

【讨论】:

  • 您可能需要注意,这通常是通过将程序拆分为多个文件并在标题中声明来实现的。
  • 是的,但另一方面,这个例子有助于理解什么时候必须定义一个函数(即在使用它之前)以及什么时候声明它就足够了。 (这与头文件和实现文件不相关)
猜你喜欢
  • 2011-04-26
  • 2013-03-26
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
  • 2017-05-09
  • 1970-01-01
  • 2019-10-05
  • 2023-02-10
相关资源
最近更新 更多