C++面向對象創建打印算術表達式樹

????????C++面向對象,實現算術表達式樹的創建和打印的案例,來源于《C++沉思錄》第八章,涉及數據抽象、繼承、多態(動態綁定)、句柄,其中句柄的使用是核心,關于句柄的較為簡單的文章鏈接點擊這里,較為復雜的文章鏈接點擊這里

????????表達式(-5)*(3+4)對應的樹如圖,包括常數、一元運算符和二元運算符的結點,結點為圖中的圓圈,“邊”用箭頭表示,一個結點或連接一個子結點、兩個子結點或不連接子結點

????????結點有三種形式:表示整數表達式,包含一個整數值,無子結點,另外兩個分別表示一元表達式和二元表達式包含一個操作符,分別有一個或兩個子結點,三種形式對應三個類

? ? ? ? 三個類抽象出來一個結點概念,為它們的基類,即結點類,有子結點的類用包裝基類指針的句柄表示“邊”,使用句柄的作用就是隱藏繼承層次,動態綁定,管理內存,避免結點復制

????????基類代碼

//基類Expr_node
class Expr_node{friend class Expr; //句柄類//因虛函數,重載<<的友元可以不在子類聲明friend std::ostream& operator<<(std::ostream&,const Expr&);int use; //計數
protected:Expr_node():use(1) { } //默認構造,計數1virtual void  print(std::ostream&) const =  0;virtual ~Expr_node(){} //虛析構
};

? ? ? ? 重載<<操作符函數代碼(句柄類對象引用隱藏繼承層次)

std::ostream& operator<<(std::ostream& o, const Expr& t)//句柄類對象t.p->print(o);return o;
}

? ? ? ?三個子類代碼

//1、包含一個整數,沒有子結點的結點類
class Int_node:public Expr_node{friend class Expr; //句柄類int n;Int_node(int k):n(k) { } //構造void print(std::ostream& o) const { o << n; }
};//2、一元運算符結點類
class Unary_node:public Expr_node{friend class Expr; //句柄類std::string op; //操作符Expr t; //句柄對象,表示"邊",指向子結點Unary_node(const std::string& a, Expr t):op(a),t(t) { }void print(std::ostream& o)const{ o << "(" << op << t << ")"; }	
};//3、二元算法符結點類
class Binary_node: public Expr_node{friend class Expr;std::string op;Expr left;Expr right;Binary_node(const std::string&a, Expr b, Expr c):op(a),left(b),right(c) { }void print(std::ostream& o)const{o << "(" << left << op << right << ")";}
};

????????句柄類代碼(包裝基類指針,動態綁定,隱藏繼承層次,引用計數避免復制)

class Expr{friend std::ostream& operator<<(std::ostream&,const Expr&);//重載輸出操作符<<Expr_node* p; //包裝基類指針
public:Expr():p(nullptr){ } //默認構造Expr(int);                            //創建一個Int_nodeExpr(const std::string& op, Expr t);  //創建一個Unary_nodeExpr(const std::string&, Expr, Expr); //創建一個Binary_node//復制管理Expr(const Expr&);              //復制構造Expr& operator=(const Expr&);   //=運算符重載~Expr();                        //析構,釋放內存
};
//句柄類構造函數,構造其包裝的基類的3個子類對象
Expr::Expr(int n)
{p = new Int_node(n);
}
Expr::Expr(const std::string& op, Expr t)
{p = new Unary_node(op,t);
}
Expr::Expr(const std::string& op, Expr left, Expr right)
{p = new Binary_node(op,left, right);
}
//復制管理
Expr::Expr(const Expr& t){ p = t.p; ++p->use; }; 
Expr& Expr::operator=(const Expr& rhs)
{rhs.p->use++;if(--p->use==0)delete p;p = rhs.p;return *this;
}
Expr::~Expr()
{if(--p->use==0)//計數為0刪除delete p; 
} 

? ? ? ? 句柄的使用,所有對象只構造一次,句柄的復制只是復制基類指針,對象引用計數,并不復制對象,隱藏了繼承層次,管理動態內存?

????????主函數測試代碼

#include <iostream>
#include <string>
int main()
{Expr t = Expr("*",Expr("-",5),Expr("+",3,4) );std:: cout << t << std::endl;t = Expr("*",t,t);std:: cout << t <<std:: endl;return 0;
}

? ? ? ? 完整測試代碼

#include <iostream>
#include <string>class Expr_node;//前置聲明,因為下面的類包裝了Expr_node*class Expr{friend std::ostream& operator<<(std::ostream&,const Expr&);//重載輸出操作符<<Expr_node* p; //包裝基類指針
public:Expr():p(nullptr){ } //默認構造Expr(int);                            //創建一個Int_nodeExpr(const std::string& op, Expr t);  //創建一個Unary_nodeExpr(const std::string&, Expr, Expr); //創建一個Binary_node//復制管理Expr(const Expr&);              //復制構造Expr& operator=(const Expr&);   //=運算符重載~Expr();                        //析構,釋放內存
};//基類Expr_node
class Expr_node{friend class Expr; //句柄類//因虛函數,重載<<的友元可以不在子類聲明friend std::ostream& operator<<(std::ostream&,const Expr&);int use; //計數
protected:Expr_node():use(1) { } //默認構造,計數1virtual void  print(std::ostream&) const =  0;virtual ~Expr_node(){} //虛析構
};//1、包含一個整數,沒有子結點的結點類
class Int_node:public Expr_node{friend class Expr; //句柄類int n;Int_node(int k):n(k) { } //構造void print(std::ostream& o) const { o << n; }
};//2、一元運算符結點類
class Unary_node:public Expr_node{friend class Expr; //句柄類std::string op; //操作符Expr t; //句柄對象,表示"邊",指向子結點Unary_node(const std::string& a, Expr t):op(a),t(t) { }void print(std::ostream& o)const{ o << "(" << op << t << ")"; }	
};//3、二元算法符結點類
class Binary_node: public Expr_node{friend class Expr;std::string op;Expr left;Expr right;Binary_node(const std::string&a, Expr b, Expr c):op(a),left(b),right(c) { }void print(std::ostream& o)const{o << "(" << left << op << right << ")";}
};//句柄類構造函數,構造其包裝的基類的3個子類對象
Expr::Expr(int n)
{p = new Int_node(n);
}
Expr::Expr(const std::string& op, Expr t)
{p = new Unary_node(op,t);
}
Expr::Expr(const std::string& op, Expr left, Expr right)
{p = new Binary_node(op,left, right);
}
//復制管理
Expr::Expr(const Expr& t){ p = t.p; ++p->use; }; 
Expr& Expr::operator=(const Expr& rhs)
{rhs.p->use++;if(--p->use==0)delete p;p = rhs.p;return *this;
}
Expr::~Expr()
{if(--p->use==0)delete p; 
} 
//重載運算符<<
std::ostream& operator<<(std::ostream& o,const Expr&t)
{t.p->print(o);return o;
}int main()
{Expr t = Expr("*",Expr("-",5),Expr("+",3,4) );std:: cout << t << std::endl;t = Expr("*",t,t);std:: cout << t <<std:: endl;/* ((-5)*(3+4))(((-5)*(3+4))*((-5)*(3+4))) */return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89076.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89076.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89076.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

力扣每日一題--2025.7.16

&#x1f4da; 力扣每日一題–2025.7.16 &#x1f4da; 3201. 找出有效子序列的最大長度 I&#xff08;中等&#xff09; 今天我們要解決的是力扣上的第 3201 題——找出有效子序列的最大長度 I。這道題雖然標記為中等難度&#xff0c;但只要掌握了正確的思路&#xff0c;就能…

SFT:大型語言模型專業化定制的核心技術體系——原理、創新與應用全景

本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我&#xff0c;一起撕掉過度包裝&#xff0c;學習真實的AI技術&#xff01; 以下基于權威期刊、會議論文及技術報告&#xff0c;對監督微調&#x…

若依前后端分離框架配置多數據庫表

若依前后端分離框架配置多數據庫表1、配置application.yml2、注釋掉application-druid.yml中的數據庫3、在DataSourceType 中添加新增的數據庫來源4、配置DruidConfig文件4、1新增注入方法&#xff0c;在DataSourceType類添加數據源枚舉4、2在DruidConfig類dataSource方法添加數…

29.安卓逆向2-frida hook技術-逆向os文件(二)IDA工具下載和使用(利用ai分析so代碼)

免責聲明&#xff1a;內容僅供學習參考&#xff0c;請合法利用知識&#xff0c;禁止進行違法犯罪活動&#xff01; 內容參考于&#xff1a;圖靈Python學院 工具下載&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取碼&#xff1…

[析]Deep reinforcement learning for drone navigation using sensor data

Deep reinforcement learning for drone navigation using sensor data 基于傳感器數據的無人機導航深度強化學習方法 評價&#xff1a;MDP無記憶性&#xff0c;使用LSTM補足缺點。PPO解決新舊策略差距大的問題。 對于環境中的障礙物&#xff0c;設置增量課程&#xff0c;障礙…

SpringBoot項目啟動報:java: 找不到符號 符號: 變量 log 的解決辦法

問題&#xff1a;使用IDEA創建SpringBoot項目&#xff0c;在項目中使用 Slf4j 注解引入log日志后&#xff0c;啟動項目&#xff0c;報如下錯誤&#xff1a;原因&#xff1a;網上找了很多博文&#xff0c;說是lombook依賴沒有引入&#xff0c;但是我的pom.xml中已經引入 lombook…

HTML基礎知識 二(創建容器和表格)

HTML 基礎知識&#xff1a;創建容器和表格&#xff08;補充版&#xff09;HTML&#xff08;超文本標記語言&#xff09;是構建網頁的基礎。容器元素用于組織內容&#xff0c;表格用于展示結構化數據&#xff0c;兩者都是網頁設計中不可或缺的部分。一、HTML 容器元素容器元素就…

多目標優化|HKELM混合核極限學習機+NSGAII算法工藝參數優化、工程設計優化,四目標(最大化輸出y1、最小化輸出y2,y3,y4),Matlab完整源碼

基本介紹 1.HKELM混合核極限學習機NSGAII多目標優化算法&#xff0c;工藝參數優化、工程設計優化&#xff01;&#xff08;Matlab完整源碼和數據&#xff09; 多目標優化是指在優化問題中同時考慮多個目標的優化過程。在多目標優化中&#xff0c;通常存在多個沖突的目標&#x…

【AI智能體】Dify 基于知識庫搭建智能客服問答應用詳解

目錄 一、前言 二、Dify 介紹 2.1 Dify 核心特點 三、AI智能體構建智能客服系統介紹 3.1 基于AI智能體平臺搭建智能客服系統流程 3.1.1 需求分析與場景設計 3.1.2 選擇合適的AI智能體平臺 3.1.3 工作流編排與調試 3.1.4 系統集成與發布 3.2 使用AI智能體構建智能客服系…

事務~~~

1、四大特性&#xff1a;A 原子性&#xff1a;對數據的一組操作&#xff0c;要么執行成功&#xff0c;要么不執行C 一致性&#xff1a;事務前后的狀態要保持一致&#xff0c;可以理解為數據的一致性I 隔離性&#xff1a;多個事務之間是隔離的&#xff0c;互不影響D 持久性&…

【Linux編譯】./build.sh: line 17: $‘\r‘: command not found

文章目錄0.運行編譯腳本遇到問題&#xff1a;方法 1&#xff1a;使用 dos2unix&#xff08;推薦&#xff09;1. 安裝 dos2unix2. 遞歸轉換整個目錄方法 2&#xff1a;使用 sed&#xff08;無需安裝額外工具&#xff09;方法 3&#xff1a;使用 tr&#xff08;僅單文件&#xff…

Weblogic歷史漏洞利用

文章目錄漏洞介紹WebLogic 漏洞概述歷史漏洞利用弱口令CVE-2014-4210CVE-2018-2894CVE-2019-2725CVE-2020-14882漏洞介紹 Oracle WebLogic Server 是一個用于開發和部署企業級 Java 應用的服務器平臺&#xff0c;但其歷史上存在多個嚴重漏洞&#xff0c;尤其以遠程代碼執行&am…

[Rust 基礎課程]使用 Cargo 創建 Hello World 項目

Cargo&#xff08;https://crates.io/&#xff09; 是 Rust 語言中最常用的構建工具和包管理工具&#xff0c;我們看看怎么通過 Cargo 創建一個 Hello World 項目并運行。 :::warning 通過官方的 Rust 安裝方式安裝 Rust&#xff0c;Cargo 是同時默認安裝好的了 ::: 首先&am…

C語言 --- 函數遞歸

函數遞歸一、什么是函數遞歸二、函數遞歸的要點三、示例1.計算n的階乘2.提取一個任意正整數的所有位數&#xff0c;按順序排列3.獲取第n個斐波那契數&#xff0c;最開始的兩個數是1&#xff0c;1四、總結一、什么是函數遞歸 函數遞歸是一種解決問題的思想&#xff0c;是將一個…

GitHub 趨勢日報 (2025年07月14日)

&#x1f4ca; 由 TrendForge 系統生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日報中的項目描述已自動翻譯為中文 &#x1f4c8; 今日獲星趨勢圖 今日獲星趨勢圖1916claude-code795the-book-of-secret-knowledge728free-for-dev547markitdown367…

PyTorch中張量(TensorFlow)操作方法和屬性匯總詳解和代碼示例

1、張量的操作匯總 下面是 PyTorch 中常見的 張量操作方法匯總&#xff0c;包括 創建、索引、變換、數學運算、廣播機制、維度操作 等內容&#xff0c;并附上詳解和代碼示例&#xff0c;便于系統學習與實戰參考。一、張量創建&#xff08;torch.tensor 等&#xff09; import t…

統一日志格式規范與 Filebeat+Logstash 實踐落地

背景 在多部門、多技術棧并存的企業環境中&#xff0c;日志收集與分析是保障系統穩定運行的核心能力之一。然而&#xff0c;不同開發團隊采用各異的日志打印方式&#xff0c;導致日志數據結構混亂&#xff0c;嚴重影響后續的收集、存儲、檢索與告警效率。 比如我們大部門就有多…

【鴻蒙HarmonyOS】鴻蒙app開發入門到實戰教程(三):實現一個音樂列表的頁面

鴻蒙里面&#xff0c;實現一個音樂播放的列表,模擬數組的數據展示 實現效果代碼實現 準備數據 songs:SongItemTypes[] [{img:https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/0.jpg,name:直到世界的盡頭,author:WANDS},{img:https://yjy-teach-oss.oss-cn…

2025年滲透測試面試題總結-2025年HW(護網面試) 47(題目+回答)

安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 2025年HW(護網面試) 47 1. UDF提權 2. 命令執行與代碼執行的區別 3. 文件包含利用姿勢 4. 漏洞復現流程 …

iPhone 數據擦除軟件評測(最新且全面)

當您準備出售、捐贈或回收 iPhone 時&#xff0c;僅僅恢復出廠設置并不足以保證您的個人數據徹底消失。專業的 iPhone 數據擦除軟件采用先進的技術&#xff0c;確保您的敏感信息永久無法恢復。本文回顧了十種流行的 iPhone 數據擦除工具&#xff0c;詳細介紹了它們的功能、優點…