【问题标题】:Abstract syntax tree in C++: classes vs. structsC++ 中的抽象语法树:类与结构
【发布时间】:2017-01-01 20:50:27
【问题描述】:

我需要在我的 C++ 程序中表示一个树层次结构(准确地说是 AST)。好的,我多次看到这种结构的例子,但有一件事我还不清楚。请告诉我为什么在 C++ 中使用类而不是结构来进行 AST 如此普遍?例如,考虑以下代码,它表示 AST 的一个节点:

class Comparison {
public:
  Node* getLhs() const { return m_lhs; }
  Node* getRhs() const { return m_rhs; }

  //other stuff
private:
  ComparisonOperator m_op;
  Node* m_lhs;
  Node* m_rhs;
};

(灵感来自https://github.com/clever-lang/clever/blob/master/core/ast.h#L150,但我丢弃了一些不必要的细节) 正如您在此处看到的,我们有两个 getter,它们返回指向私有数据成员的指针,而这些指针甚至不是 const!据我所知,这打破了封装。那么为什么不是 AST 节点的结构(默认情况下所有成员都是公共的)呢?您将如何在 C++ 中实现 AST(我的意思是处理可访问性问题)? 我个人认为结构非常适合此类任务。

我发布了来自任意项目的代码,但您可能会经常看到这种做法(带有 AST 封装破坏方法的类)。

【问题讨论】:

  • 我会说这里没有实际答案,而是基于意见的答案。
  • 您的问题实际上不是关于 AST,而是在对象中隐藏私有成员是否好。
  • 这让我开始抱怨为什么这些吸气剂不好。但我会避免。它非常基于意见。
  • C++ 中classstruct 之间没有显着差异。两者都用于定义类。两者之间的选择纯粹是风格。
  • 它可以防止人们将m_lhs 更改为指向另一个节点。

标签: c++ oop abstract-syntax-tree encapsulation getter


【解决方案1】:

请告诉我为什么在 C++ 中对 AST 使用类而不是结构如此普遍? [..] 我个人认为结构体非常适合此类任务。

没关系; C++ 没有结构。当您编写struct 时,您正在创建一个类。

要么写struct,要么写class。然后要么写public,要么写private

有些人选择class,因为他们认为使用struct定义的类不能包含私有成员、成员函数等。他们错了。

有些人选择class,因为他们更喜欢将struct 保留在没有私有成员或成员函数的“简单”类型后面,纯粹是出于风格原因。这是主观的,完全取决于他们。 (我大部分自己做类似的事情。)

该标准确实在极少数地方使用术语“结构”和“结构”,有时显然是指代 POD 类的快捷方式,但其他时候错误(例如 C++14 §C.1.2/3.3 “结构是类”)。这导致一些人质疑 C++ 没有结构的事实(包括暗示“结构”是类的一个子集,尽管这个概念定义得不够好,无法被正式接受)。不管怎样,std::is_class trait 的行为让事情变得非常清楚。

【讨论】:

    【解决方案2】:

    好吧,考虑一下这段代码:

    class Parent {
    public:
        int x;
        void test();
    
    private:
        int y;
    };
    
    class Child : public Parent {
    public:
        int z;
    };
    

    现在使用 struct 关键字也是一样的:

    struct Parent {
        int x;
        void test();
    
    private:
        int y;
    };
    
    struct Child : Parent {
        int z;
    };
    

    有些人更喜欢class 关键字来明确某物是一个类,而struct 则用于某些数据类

    【讨论】:

      【解决方案3】:

      也许像下面这样的模式是可以接受的?

      class Comparison {
      public:
        const Node* lhs() const { return m_lhs; }
        const Node* rhs() const { return m_rhs; }
        Node* mutable_lhs() const { return m_lhs; }
        Node* mutable_rhs() const { return m_rhs; }
      
        //other stuff
      private:
        ComparisonOperator m_op;
        Node* m_lhs;
        Node* m_rhs;
      };
      

      如果程序员打算得到一个可变节点,那么至少他的意图是明确的?

      顺便说一句,即使使用mutable_lhs(),他也只能获得指向可变节点的指针,但他仍然无法更改指针本身。如果使用没有明确的公共/私有规范的结构,他将失去这种保护。

      【讨论】:

      • “如果使用 struct,他会失去这种保护。” - 怎么会这样?
      • @UnholySheep: obj.m_lhs = nullptr 将丢失原始节点。相比之下,obj.mutable_lhs() = nullptr 将是无害的(无用的)。
      • 这是 publicprivate+ 吸气剂的问题 - 这不是 structclass 的问题。如果我只是在您的代码中将 class 关键字替换为 struct,它不会降低安全性。
      • @UnholySheep:同意,尽管据我所知 struct 和 class 之间的唯一区别是 struct 的成员默认情况下是公共的。否则它们是同一回事。所以是的,在我明确指定公共/私有的代码中,使用结构或类都是一样的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-01
      • 2017-12-05
      • 2017-07-26
      • 2014-02-04
      • 2011-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多