【C++學習手札】一文帶你初識運算符重載

??????????????????????????????????????? ?食用指南:本文在有C基礎的情況下食用更佳???

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? 🍀本文前置知識:?C++類?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??今日夜電波:クリームソーダとシャンデリア—Edo_Ame江戶糖

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1:20?━━━━━━?💟──────── 3:40
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????🔄 ? ?? ? ? ? ?? ? ???

??????????????????????????????????????💗關注👍點贊🙌收藏您的每一次鼓勵都是對我莫大的支持😍?


目錄

💓一、運算符重載基本概念

什么是運算符重載?

運算符重載簡要干貨

可重載的運算符有哪些??

💗二、前置知識-友元函數?

?什么是友元函數?

?友元函數的語法

?💞三、運算符重載

運算符重載的語法

一步一步帶你實現運算符重載(以<<為例)

運算符重載作為成員函數以及全局函數的實現(以+為例)

全局函數

成員函數

💕四、++和--運算符重載?(重要、常用)

💘具體實現用例?


一、運算符重載基本概念

什么是運算符重載?

????????運算符重載, 就是對已有的運算符重新進行定義, 賦予其另一種功能, 以適應不同
的數據類型。
????????運算符重載(operator overloading)只是一種”語法上的方便”,也就是它只是另一種函
數調用的方式。

????????在 c++中, 可以定義一個處理類的新運算符。 這種定義很像一個普通的函數定義,只是函數的名字由關鍵字 operator 及其緊跟的運算符組成。 差別僅此而已。 它像任何其他函數一樣也是一個函數, 當編譯器遇到適當的模式時, 就會調用這個函數。

運算符重載簡要干貨

????????運算符重載的目的:簡化操作 讓已有的運算符 適應適應不同的數據類型。
????????語法:函數的名字由關鍵字operator及其緊跟的運算符組成
????????比如:重載+運算符 ==>? ? ?operator+ 重載=號運算? ? ?==>? ? ?operator=
????????注意:重載運算符 不要更改 運算符的本質操作(+是數據的相加 不要重載成相減)

? ? ? ? ?栗子:(以下為重載了<<運算符的類)

class Data
{friend ostream& operator<<(ostream& out, Data& ob);//友元函數,經常與運算符重載搭配使用
private:int a;int b;
public:Data(){cout << "無參的構造函數" << endl;a = 0;b = 0;}Data(int a, int b) :a(a), b(b){cout << "有參構造" << endl;//this‐>a = a;//this‐>b = b;}void showData(void){cout << "a = " << a << ", b= " << b << endl;}~Data(){cout << "析構函數函數" << endl;}
};ostream& operator<<(ostream& out, Data& ob){out << "a = " << ob.a << ", b = " << ob.b;return out;}

? ? ? ? 解釋:

????????為了簡化類中訪問私有數據較為困難的問題,運用友元函數(下小點會提到)同重載運算符的結合,得以運用我們較為常用的<<直接輸出數據。

可重載的運算符有哪些??

????????幾乎 C 中所有的運算符都可以重載, 但運算符重載的使用時相當受限制的。 特別是不能使用 C 中當前沒有意義的運算符(例如用**求冪)不能改變運算符優先級, 不能改變運算符的參數個數。 這樣的限制有意義, 否則, 所有這些行為產生的運算符只會混淆而不是澄清寓語意。

? ? ? ? 一張圖囊括~?


二、前置知識-友元函數?

?什么是友元函數?

一句話概括:C++允許 友元 訪問 私有數據。

?友元函數的語法

friend+定義的函數

? ? ? 注意:? friend關鍵字只出現在聲明處 其他類、類成員函數、全局函數都可聲明為友元 友元函數不是類的成員,不帶this指針 友元函數可訪問對象任意成員屬性,包括私有屬性。

????????栗子: (創建一個房間類,你只準許你的朋友進入你的臥室,但是客廳是誰都可以進的)

class Room{//將goodGayVisit作為類的友元函數//goodGayVisit 訪問 類中所有數據 但是 它不是類的成員friend void goodGayVisit(Room & room);private:string bedRoom;//臥室public:string sittingRoom;//客廳public: Room(){this-> bedRoom = "臥室";this-> sittingRoom = "客廳";}};// 普通全局函數 作為 類的友元//好基友 訪問 我的房間void goodGayVisit(Room & room){cout << "好基友訪問了你的" << room.sittingRoom << endl;cout << "好基友訪問了你的" << room.bedRoom << endl;//ok}void test01(){Room myRoom;goodGayVisit(myRoom);
}

? ? ? ? friend在這里可以訪問對象任意成員屬性,包括私有屬性。因此,本來不能訪問的私有數據,在friend的情況下就可以訪問了!結果如下:

? ? ? ? 此為普通全局函數 作為 類的友元 。當然,也有類的某個成員函數 作為 另一個類的友元;一個類整體 作為 另一個類的友元等等。

????????而我們的友元函數大多應用在重載運算符上!

?????????本文僅僅對友元函數做簡單介紹,如果大家需要詳解,請在評論區或者私信踢我一腳o(╯□╰)o,作者肯定會出一篇的!


?三、運算符重載

運算符重載的語法

(根據自身改變的返回類型)operator + 重載的運算符(根據實際情況改變的傳參)
  1. 函數聲明:運算符重載是通過在類中定義特殊的成員函數來實現的。這些成員函數被稱為運算符重載函數。例如,如果要重載"+"運算符,則需要在類中聲明一個名為"operator+"的函數。

  2. 函數名:運算符重載函數的命名規則是以"operator"關鍵字開始,后面跟著要重載的運算符符號。例如,要重載"+“運算符,函數名應為"operator+”。

  3. 參數列表:運算符重載函數的參數列表取決于所重載的運算符。例如,對于二元運算符如"+", “-”, “*”, “/“等,參數列表應包含一個額外的參數,表示右操作數。對于一元運算符如”++”, "– – "等,參數列表不需要額外的參數。

  4. 返回類型:運算符重載函數的返回類型取決于所重載的運算符。例如,對于"+"運算符,返回類型通常是所操作對象的類型。

  5. 成員函數或友元函數:運算符重載函數可以作為類的成員函數或友元函數來定義。成員函數形式的運算符重載函數將使用對象本身作為左操作數,而友元函數形式的運算符重載函數將不使用任何對象。


一步一步帶你實現運算符重載(以<<為例)

? ? ? ? 注意:此代碼未能實現重載 下文為對用cout來輸出類的一個引入

#define _CRT_SECURE_NO_WARNINGS 01
#include <iostream>
#include<string.h>using namespace std;class Person{private:char* name;int num;public:Person(char* name, int num){this-> name = new char[strlen(name) + 1];strcpy(this-> name, name);this-> num = num;cout << "有參構造" << endl;}//普通的成員函數void printPerson(void){cout << "name = " << name << ", num = " << num << endl;}~Person(){if (this-> name != NULL){delete[] this-> name;this-> name = NULL;}cout << "析構函數" << endl;}};int main(int argc, char* argv[]){char arr[] = "lucy";Person ob1(arr, 18);//普通的成員函數 遍歷信息//ob1.printPerson();//cout默認輸出方式 無法識別 自定義對象 輸出格式cout<<ob1<<endl;//errreturn 0;}

? ? ? ? 運行改代碼,我們發現編譯器報錯!如下圖:

?????????這個時候我們就需要對運算符進行重載了!

????????那么問題又來了?如何重載運算符呢?根據上文所提到的語法,我們做出以下的操作:

????????運用operator來重載<<運算符

 ostream& operator<<(ostream& out, Person& ob)//out=cout, ob =ob1{//重新實現 輸出格式out << ob.name << ", " << ob.num;//每次執行為 返回值得到coutreturn out;}

? ? ? ? 注意:ostream為cout的類型,定義ostream&為返回類型是為了作為起到鏈接的效果,如:

cout<<ob1<<ob2<<endl;ostream&返回out,然后再次被后面所調用,一直反復調用下去。

????????然而,進行了運算符重載,就能實現我們想要的效果了嗎?答案是不能,見下圖:

?????????造成這樣的原因是什么呢?還是類的封裝問題,私有的數據不能被外界所訪問!這時,我們就需要用到友元函數來幫助我們實現了!

?????????于是,我們將operator<<設置成友元:

#define _CRT_SECURE_NO_WARNINGS 01
#include <iostream>
#include<string.h>using namespace std;class Person{//設置成友元函數 在函數內 訪問Person類中的所有數據friend ostream & operator<<(ostream & out, Person & ob);private:char* name;int num;public:Person(char* name, int num){this-> name = new char[strlen(name) + 1];strcpy(this-> name, name);this-> num = num;cout << "有參構造" << endl;}//普通的成員函數void printPerson(void){cout << "name = " << name << ", num = " << num << endl;}~Person(){if (this-> name != NULL){delete[] this-> name;this-> name = NULL;}cout << "析構函數" << endl;}};ostream& operator<<(ostream& out, Person& ob)//out=cout, ob =ob1{//重新實現 輸出格式out << ob.name << ", " << ob.num;//每次執行為 返回值得到coutreturn out;}int main(int argc, char* argv[]){char arr[] = "lucy";Person ob1(arr, 18);//普通的成員函數 遍歷信息//ob1.printPerson();//cout默認輸出方式 無法識別 自定義對象 輸出格式cout<<ob1<<endl;//errreturn 0;}

? ? ? ? 實現效果如下:


運算符重載作為成員函數以及全局函數的實現(以+為例)

全局函數

????????這里同上面的栗子大致一樣,不過多敘述

#include <iostream>#include<string.h>using namespace std;class Person{//設置成友元函數 在函數內 訪問Person類中的所有數據friend ostream & operator<<(ostream & out, Person & ob);friend Person operator+(Person & ob1, Person & ob2);private:char* name;int num;public:Person(){this-> name = NULL;this-> num = 0;cout << "無參構造" << endl;}Person(char* name, int num){this-> name = new char[strlen(name) + 1];strcpy(this-> name, name);this-> num = num;cout << "有參構造" << endl;}//普通的成員函數void printPerson(void){cout << "name = " << name << ", num = " << num << endl;}~Person(){if (this-> name != NULL){delete[] this-> name;this-> name = NULL;}cout << "析構函數" << endl;}};//全局函數作為友元 完成運算符重載<<ostream & operator<<(ostream & out, Person & ob)//out=cout, ob =ob1{//重新實現 輸出格式out << ob.name << ", " << ob.num;//每次執行為 返回值得到coutreturn out;}//全局函數作為友元 完成運算符重載+Person operator+(Person & ob1, Person & ob2)//ob1 ob2{ //name+name(字符串追加)char* tmp_name = new char[strlen(ob1.name) + strlen(ob2.name) + 1];strcpy(tmp_name, ob1.name);strcat(tmp_name, ob2.name);//num+num(數值相加)int tmp_num = ob1.num + ob2.num;Person tmp(tmp_name, tmp_num);//釋放tmp_name的空間if (tmp_name != NULL){delete[] tmp_name;tmp_name = NULL;}return tmp;}void test02(){char arr[] = "lucy";Person ob1(arr, 18);  char arr2[] = "bob";Person ob2(arr2, 19);cout << ob1 << endl;cout << ob2 << endl;//Person ob3 = operator+(ob1,ob2);Person ob3 = ob1 + ob2;cout << ob3 << endl;}int main(int argc, char* argv[]){test02();return 0;}

成員函數

#include <iostream>#include<string.h>using namespace std;class Person{ //設置成友元函數 在函數內 訪問Person類中的所有數據friend ostream & operator<<(ostream & out, Person & ob);private:char* name;int num;public:Person(){this-> name = NULL;this-> num = 0;cout << "無參構造" << endl;}Person(char* name, int num){this-> name = new char[strlen(name) + 1];strcpy(this-> name, name);this-> num = num;cout << "有參構造" << endl;}//成員函數 完成運算符重載 ob1用this代替 ob2用參數ob代替Person operator+(Person & ob){//this ==> &ob1//name+name(字符串追加)char* tmp_name = new char[strlen(this-> name) + strlen(ob.name) + 1];strcpy(tmp_name, this-> name);strcat(tmp_name, ob.name);//num+num(數值相加)int tmp_num = this-> num + ob.num;Person tmp(tmp_name, tmp_num);//釋放tmp_name的空間if (tmp_name != NULL){delete[] tmp_name;tmp_name = NULL;}return tmp;}//普通的成員函數void printPerson(void){cout << "name = " << name << ", num = " << num << endl;}~Person(){if (this-> name != NULL){delete[] this-> name;this-> name = NULL;}cout << "析構函數" << endl;}};//全局函數作為友元 完成運算符重載<<ostream & operator<<(ostream & out, Person & ob)//out=cout, ob =ob1{//重新實現 輸出格式out << ob.name << ", " << ob.num;//每次執行為 返回值得到coutreturn out;}void test03(){char arr[] = "lucy";char arr2[] = "bob";Person ob1(arr, 18);Person ob2(arr2, 19);//Person ob3 = ob1.operator+(ob2);Person ob3 = ob1 + ob2;cout << ob3 << endl;}int main(int argc, char* argv[]){ test03();return 0;}

? ? ? ? 在運算符重載運算符時,如果我們以成員函數的方式定義,則可以直接訪問類中的數據,無需再使用友元函數來定義。因此我們在重載運算符時最好是以成員函數的方式重載!


四、++和--運算符重載?(重要、常用)

? ? ? ? 不知道大家有沒有一個疑惑如果我們實現前置+ +、后置+ +以及前置- -、后置--,運用operator時如何區分他們呢?

? ? ? ? 此時,我們又要提到一個概念,當編譯器看到++a(前置++),它就調用operator++(a),當編譯器看到a++(后置++),它就會去調用operator++(a,int)。 - -也是同樣的道理,具體實現如下:

具體實現用例?

#include <iostream>using namespace std;class Data{friend ostream & operator<<(ostream & out, Data & ob);private:int a;int b;public:Data(){cout << "無參的構造函數" << endl;a = 0;b = 0;}Data(int a, int b) :a(a), b(b){cout << "有參構造" << endl;//this‐>a = a;//this‐>b = b;}void showData(void){cout << "a = " << a << ", b= " << b << endl;}~Data(){cout << "析構函數函數" << endl;}//成員函數 重載前置++ ++ob1 (先加 后使用)//編譯器 默認識別 operator++(a) //但是a可以用this代替 從而化簡 operator++()Data & operator++()//++ob1{ //先加a++;//this‐>a = this‐>a +1b++;//this‐>b = this‐>b +1//后使用return *this;}//成員函數 重載后置++ ob1++ (先使用 后加)//編譯器 默認識別 operator++(a,int) //但是a可以用this代替 從而化簡 operator ++(int)Data & operator++(int)//ob1++{//先使用(備份加之前的值)static Data old = *this;//后加a++;b++;//返回備份值return old;}//重載前置‐‐ ‐‐ob3//編譯器 默認識別 operator++(a) //但是a可以用this代替 從而化簡 operator‐‐()Data & operator--(){//先減a--;b--;//后使用(返回)return *this;}//重載后‐‐ ob4‐‐//編譯器 默認識別 operator++(a,int) //但是a可以用this代替 從而化簡 operator++(int)Data & operator--(int){//先使用static Data old = *this;//再減a--;b--;return old;}};//普通全局函數 作為類的友元 重載<<運算符ostream & operator<<(ostream & out, Data & ob){out << "a = " << ob.a << ", b = " << ob.b;return out;}void test01(){Data ob1(10, 20);ob1.showData();//重載<<直接輸出自定義對象的值//operator<<(cout,ob1);cout << ob1 << endl;//成員函數 重載 ++運算符cout << ++ob1 << endl;Data ob2(10, 20);cout << ob2++ << endl;cout << ob2 << endl;//成員函數 重載 ‐‐運算符Data ob3(10, 20);cout << "ob3 " << ob3 << endl;cout << --ob3 << endl;Data ob4(10, 20);cout << "ob4 " << ob4 << endl;cout << ob4-- << endl;cout << "ob4 " << ob4 << endl; }int main(int argc, char* argv[]){test01();return 0;}

????????效果如下:?


????????????????感謝你耐心的看到這里?( ′・?・` )比心,如有哪里有錯誤請踢一腳作者o(╥﹏╥)o!??

?????????????????????????????????

?????????????????????????????????????????????????????????????????給個三連再走嘛~??????

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

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

相關文章

ID3 決策樹

西瓜數據集D如下: 編號色澤根蒂敲聲紋理臍部觸感好瓜1青綠蜷縮濁響清晰凹陷硬滑是2烏黑蜷縮沉悶清晰凹陷硬滑是3烏黑蜷縮濁響清晰凹陷硬滑是4青綠蜷縮沉悶清晰凹陷硬滑是5淺白蜷縮濁響清晰凹陷硬滑是6青綠稍蜷濁響清晰稍凹軟粘是7烏黑稍蜷濁響稍糊稍凹軟粘是8烏黑稍蜷濁響清晰…

idea cannot download sources 解決方法

問題 點擊class文件右上角下載源碼失敗 解決方案 找到idea terminal 控制臺cd 至maven工程執行 mvn dependency:resolve -Dclassifiersources

【IMX6ULL驅動開發學習】04.應用程序和驅動程序數據傳輸和交互的4種方式:非阻塞、阻塞、POLL、異步通知

一、數據傳輸 1.1 APP和驅動 APP和驅動之間的數據訪問是不能通過直接訪問對方的內存地址來操作的&#xff0c;這里涉及Linux系統中的MMU&#xff08;內存管理單元&#xff09;。在驅動程序中通過這兩個函數來獲得APP和傳給APP數據&#xff1a; copy_to_usercopy_from_user …

24屆近3年上海電力大學自動化考研院校分析

今天給大家帶來的是上海電力大學控制考研分析 滿滿干貨&#xff5e;還不快快點贊收藏 一、上海電力大學 學校簡介 上海電力大學&#xff08;Shanghai University of Electric Power&#xff09;&#xff0c;位于上海市&#xff0c;是中央與上海市共建、以上海市管理為主的全日…

stack 、 queue的語法使用及底層實現以及deque的介紹【C++】

文章目錄 stack的使用queue的使用適配器queue的模擬實現stack的模擬實現deque stack的使用 stack是一種容器適配器&#xff0c;具有后進先出&#xff0c;只能從容器的一端進行元素的插入與提取操作 #include <iostream> #include <vector> #include <stack&g…

Layui列表復選框根據條件禁用

// 禁用客服回訪id有值的復選框res.data.forEach(function (item, i) {if (item.feedbackEmpId) {let index res.data[i][LAY_TABLE_INDEX];$(".layui-table tr[data-index"index"] input[typecheckbox]").prop(disabled,true);$(".layui-table tr[d…

【WebRTC---源碼篇】(二十四)GCC獲取碼率后的分配

RtpTransportControllerSend::PostUpdates 配置碼率 // Contains updates of network controller comand state. Using optionals to // indicate whether a member has been updated. The array of probe clusters // should be used to send out probes if not empty. // 包…

【SpringBoot】89、SpringBoot中使用@Transactional進行事務管理

事務是一組組合成邏輯工作單元的操作,雖然系統中可能會出錯,但事務將控制和維護事務中每個操作的一致性和完整性。 1、SpringBoot 引用說明 新建的 Spring Boot 項目中,一般都會引用 spring-boot-starter 或者 spring-boot-starter-web,而這兩個起步依賴中都已經包含了對…

EV 錄屏修復小工具

參考這篇文章, EV錄制文件損壞-修復方法, 我用 C# 寫了一個小程序. 倉庫: github.com/SlimeNull/EvRepair 下載: github.com/SlimeNull/EvRepair/Releases 鏡像: gitee.com/slimenull/EvRepair/releases 覺得還不錯的話, 點個星星 推薦使用的幾個理由: 內嵌 ffmpeg 和 recov…

Linux學習之初識Linux

目錄 一.Linux的發展歷史及概念 1.什么是Linux UNIX發展的歷史&#xff1a; Linux發展歷史&#xff1a; 2. 開源 商業化發行版本 二. 如何搭建Linux環境 Linux 環境的搭建方式主要有三種&#xff1a; 1. 直接安裝在物理機上 2. 使用虛擬機軟件 3. 使用云服務器 三. …

沒學C++,如何從C語言絲滑過度到python【python基礎萬字詳解】

大家好&#xff0c;我是紀寧。 文章將從C語言出發&#xff0c;深入介紹python的基礎知識&#xff0c;也包括很多python的新增知識點詳解。 文章目錄 1.python的輸入輸出&#xff0c;重新認識 hello world&#xff0c;重回那個激情燃燒的歲月1.1 輸出函數print的規則1.2 輸入函…

idea 使用debug 啟動項目的時候 出現 Method breakpoints may dramatically slow down debugging

問題: 1. 寫了一段時間的代碼&#xff0c;在debug啟動項目后提示&#xff1a;Method breakpoints may dramatically slow down debugging 但是正常啟動是可以的&#xff0c;debug不行。 2. idea 里面的項目&#xff0c;很多地方都有斷點&#xff0c;現在想要取消全部的斷點…

Redis——hash類型詳解

概述 Redis本身就是鍵值對結構&#xff0c;而Redis中的value可以是哈希類型&#xff0c;為了區分這兩個鍵值對&#xff0c;Redis中的鍵值對是key-value&#xff0c;而value中的哈希鍵值對則是field-value&#xff0c;其中value必須是字符串 下面介紹一些Redis的hash類型的常用…

Vue中拖動排序功能,引入SortableJs,前端拖動排序。

背景&#xff1a; 作為一名前端開發人員&#xff0c;在工作中難免會遇到拖拽功能&#xff0c;分享一個github上一個不錯的拖拽js庫&#xff0c;能滿足我們在項目開發中的需要&#xff0c;支持Vue和React&#xff0c;下面是我在vue后臺項目中中使用SortableJS的使用詳細流程&am…

html實現iphone同款開關

一、背景 想實現一個開關的按鈕&#xff0c;來觸發一些操作&#xff0c;網上找了總感覺看著別扭&#xff0c;忽然想到iphone的開關挺好&#xff0c;搞一個 二、代碼實現 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&qu…

HDFS原理剖析

一、概述 HDFS是Hadoop的分布式文件系統&#xff08;Hadoop Distributed File System&#xff09;&#xff0c;實現大規模數據可靠的分布式讀寫。HDFS針對的使用場景是數據讀寫具有“一次寫&#xff0c;多次讀”的特征&#xff0c;而數據“寫”操作是順序寫&#xff0c;也就是…

STM32 LL庫+STM32CubeMX--LED呼吸燈

一、前期準備 硬件&#xff1a;STM32F103C8T6開發板調試工具&#xff1a;DAPLink(本次使用)或USB-TTL開發環境&#xff1a;STM32CubeMX、Keil、Vscode(可選)LED&#xff1a;使用PA0(TIM2_CH1)輸出PWM&#xff0c;LED的陰極接GND 二、使用定時器中斷產生PWM STM32F103C8T6在72…

scope,deep穿透的實際應用

一.父組件代碼 <template><div id"app"><h1 class"box"><pageName> </pageName></h1></div> </template><script> import pageName from "../src/components/pageName.vue"; export de…

Java中的==和equals():區別詳解

大家好&#xff01;在 Java 編程中&#xff0c;比較對象的相等性是一個常見的任務。然而&#xff0c;你是否知道在 Java 中有兩種不同的方法來比較對象的相等性&#xff1a; 操作符和 equals() 方法&#xff1f;本文將深入探討這兩種方法之間的區別以及何時使用它們。 操作符 …

arcgis pro3.0-3.0.1-3.0.2安裝教程大全及安裝包下載

一. 產品介紹&#xff1a; ArcGIS Pro 這一功能強大的單桌面 GIS 應用程序是一款功能豐富的軟件&#xff0c;采用 ArcGIS Pro 用戶社區提供的增強功能和創意進行開發。 ArcGIS Pro 支持 2D、3D 和 4D 模式下的數據可視化、高級分析和權威數據維護。 支持通過 Web GIS 在一系列 …