C++_預設建構函式和過載以及設計模式

辰令發表於2024-12-09

類和類之間關係

類外:  靜態變數,是在編譯階段就分配好空間,物件還沒建立的時候就有了空間

類:類-物件-物件是類的一個例項
   類頭(class head)和類體(class body)。 將資料和行為封裝在單個單元中--封裝
    成員變數  成員函式 成員變數稱為屬性(property);成員函式稱為方法(method)
	   靜態成員變數 在記憶體中只有一個副本,為所有類的例項共享。
          靜態成員變數必須在類中宣告,類外定義。宣告時使用關鍵字static ,定義的時候不用加static	
       靜態成員函式: 屬於類不屬於物件,靜態函式能操作靜態資料,不能操作非靜態資料	  
	   共享(static),又要實現不能修改(const),static前面加上const,
	成員函式的--引數和區域性變數 
    成員函式--其他類的靜態方法
    成員變數--引用其他類的全域性變數 其他類的屬性  其他類的例項-其他類的物件		
	  
	空類:  
       在空類情況下編譯器會自動生成以下6個預設成員函式。
  
親疏遠近
       類之間的關係強弱順序是這樣的:繼承(泛化) > 組合 > 聚合 > 關聯 > 依賴。
關係:  
    繼承--泛化關係 is a  Generalization   
	實現--Realization
	    虛擬函式    中使用的關鍵詞是 virtual    :虛擬函式是在基類中宣告為虛擬函式的函式,可以有預設實現,在基類中有預設的實現,但也可以被子類重寫
		純虛擬函式 定義純虛擬函式的語法是在函式宣告後面加上 “= 0” 基類中宣告但是沒有定義的虛擬函式,它的定義留給了派生類
		如果類中存在純虛擬函式,則這個類被稱為抽象類,抽象類不能被例項化
	    C++透過 虛擬函式(Virtual Function) 實現執行時多型性	
        函式的重寫:  派生類中重新定義基類--方法具有相同的函式名-相同的引數列表--相同的返回值型別	
           重寫是在派生類中重新定義虛擬函式,函式簽名必須與基類中的虛擬函式一致		
    組合關係 contains a   組合(Composition) 同生共死 的關係 
    聚合關係 has a 
    關聯(Assocition) 
    依賴關係 use a

C++ 過載(Overloading)

     在同一個作用域內宣告多個同名的函式或運算子
    過載函式 
        
		const修飾類成員函式,實際限制的是*this,表明該成員函式不能對類的任何成員進行修改
		const物件只能呼叫不會修改資料成員的const方法
		 運算子過載 :返回值型別 operator運算子(引數列表)
		
    過載運算子--新的運算子行為	--不能改變運算子的優先順序和結合性 運算物件數量和格式不能改變  不能發明新的運算子	
	      有兩個方法,第一種就是在類內部寫成員函式實現,
		              第二種全域性函式實現,兩個方法都有一個功能的函式名稱
		以加號為例:
					  operator+(), 這個函式名稱是固定
		    全域性函式過載+號運算子  Person p3 = operator+(p1,p2);我們習慣簡寫成 p3 = p1 + p2 的程式碼形式
			成員函式過載+號運算子  Person p3 = p1.operator+(p2);我們習慣簡寫成 p3 = p1 + p2 的程式碼形式
	 說明: 運算子是不能過載  只能過載成全域性函式的運算子   只能過載成成員函式的運算子
	 
	左值與右值(Lvalue/Rvalue) 
	     同類物件之間可以透過賦值運算子“=”互相賦值 如果沒有經過過載相當於值的複製, 稱為“淺複製”。
	    左值可以取地址、位於等號左邊;而右值沒法取地址,位於等號右邊。
    左值引用和右值引用
        傳統的C++引用,即是左值引用		
	    右值引用:
            右值引用使用 && 符號來宣告,表示對右值的引用
			右值不具名,只能透過引用的方式找到
	std::move(),它可以將一個左值強制轉換為右值引用  
	
	移動語義
	    物件的所有權轉移 左值物件轉換為右值物件,使得後續的操作可以使用移動語義而非複製語義
	    
	
 運算子過載原型 函式原型:返回值型別 operator運算子(引數列表)
	
	傳輸值(複製和移動  copy and move ) 使用了相同的符號--將左值和右值的處理分離開來,左值-複製賦值和複製構造  右值-移動賦值和移動構造
	複製操作
	  X(const X&)
	  X& operator=(const X&)
	移動操作 
	  X(X &&)
	  X& operator=(X&&)
	構造和析構
	  X()  ~X()
    
    取地址及const取地址運算子		
        X* operator&()
        const X* operator&() const
    C++運算子 
	    * 指標運算子
        & 取地址符 返回運算元的記憶體地址 
		* 是一元運算子,返回運算元所指定地址的變數的值
        & 引用運算子  資料型別與變數名稱的中間。

       形參實際是重新在棧申請了變數空間,增大了記憶體開銷,而引用可以理解為替換符,並沒有申請多餘的變數空間。


    std::forwad() 相應實參是左值,則被轉發為左值;同理如果相應實參為右值,則被轉換為右值。		   

預設引入

C編譯器
      C 語言標準--  main函式:程式的預設入口點 在大多數情況下,main函式是C程式的入口點
     非標準操作--  藉助編譯器特性和連結器選項,我們可以指定其他函式作為程式的入口
	   還可以透過連結指令碼(linker script)來控制程式的入口點

C++ 編譯器會自動生成以下6個預設成員函式。
     哪些:    預設的 建構函式、解構函式、
               預設過載取址運算子函式   預設過載取址運算子函式const函式
			   複製建構函式、以及預設過載賦值運算子函式
               預設移動建構函式(c++11)    預設過載移動賦值運算子函式(c++11)
			   
			         C++預設複製建構函式執行的是淺複製操作
                     = ,但移動建構函式是構造了一個新物件,移動賦值運算子是對已存在的物件賦值
       複製,然後再銷燬臨時物件的資源
	    即將被銷燬的物件移動到接收物件,而不是複製
		std::move()用於將左值轉換為右值引用,允許資源的有效轉移	
            std::move()是一個標準模板函式,它可以將一個左值轉換為一個右值引用,從而觸發移動語義。
			std::move()並不真正移動任何東西,只是改變了物件的型別			
	 
   什麼時候:  預設建構函式“被需要”的時候編譯器才會幫我們合成
   充要條件,必要不充分條件
   
     如果沒有經過過載,“=” 的作用就是將賦值號右側物件的值 
	    過載賦值操作會將物件的成員變數逐個複製到另一個物件中--深複製”
	 記憶體複製是指將一段記憶體中的資料複製到另一段記憶體中。通常使用記憶體複製函式如memcpy()或std::copy()來實現

    std::forward()

 預設引入-無需顯式地匯入
      Rust -預設引入std庫--CORE庫、ALLOC庫 STD庫
      Cangjie  預設引入 core   std.core 包不需要顯式匯入,預設匯入  core 包是標準庫的核心包,提供了適用倉頡語言程式設計最基本的一些 API 能力
      Java 預設引入的 java.lang	     
	  Python 預設引入 __built_in__ __main__     

繼承-封裝-多型

  物件導向設計(Object-Oriented Design)--原始碼依賴關係-以物件為手段來對原始碼中的依賴關係進行控制的能力
     封裝 特性其實並不是物件導向程式設計所獨有的。其實,c 語言也支援完整的封裝
	      C++透過在程式語言層面引入 public、private、protected 這些關鍵詞,部分維護了封裝性
     繼承 的主要作用是讓我們可以在某個作用域內對外部定義的某一組變數與函式進行覆蓋。這事實上也是 c 程式設計師早在物件導向程式語言發明之前就一直在做的事
	     C++的繼承-便利和易用
	 多型: 例如:UNIX 作業系統強制要求每個 IO 裝置都要提供 open、close、read、write 和 seek 這 5 個標準函式,多型其實不過就是函式指標的一種應用
	      C++中,類中的每個虛擬函式(virtual function),讓多型變得更安全和便於使用
     物件導向程式設計 其實是對程式間接控制權的轉移進行了約束。外掛式架構就 allows the plugin architecture to be used anywhere, for anything.
類定義:將資料和行為封裝在單個單元中--封裝	
  定義和使用其他類
  類(class)中的公共函式和私有成員變數
 
類--繼承
      C++11標準引入final說明符它告訴編譯器該虛擬函式不能被派生類重寫

多型:C++的多型性體現在兩個方面:執行時多型和編譯時多型
      透過繼承、虛擬函式和運算子過載等方式實現
    重寫(override) 	
	
	而過載是在同一作用域內定義多個函式,函式名和返回值型別一致但 函式的簽名不一致。
	過載(overload
    C++透過 函式過載(Function Overloading) 和 模板(Template) 實現編譯時多型性 
	     過載 指的是在同一作用域內函式的函式名不變,可以有變化的是函式的引數列表,
		       具體指的是引數列中的引數數量、引數型別和引數的順序可以變換。
		 模板是一種通用的程式設計機制,可以根據所傳遞的型別引數來生成特定的函式或類。函式模板和類别範本 template
	C++透過 虛擬函式(Virtual Function) 實現執行時多型性--重寫(override)的意思更接近覆蓋
	   override說明符,這個說明符必須放到虛擬函式的尾部,它明確告訴編譯器這個虛擬函式需要覆蓋基類的虛擬函式

繼承--泛化關係 is a  Generalization
    繼承與派生是同一個過程的兩種描述方式。 
     從子類角度,由父類繼承;從父類角度,子類是派生出的
關聯關係:聚合和組合的最關鍵區別是兩個物件的生命週期是否一致,而不是出現的形式
	組合關係 contains a   組合(Composition) 同生共死 的關係
	      被組合的物件 在 組合物件建立的 同時或者建立之後 建立,在組合物件銷燬之前銷燬
    聚合關係 has a 
	
    關聯(Assocition) 
	     單向關聯、雙向關聯、自關聯將一個類的物件 作為 另一個類的成員變數。

	依賴關係 use a 依賴(Dependency)關係是一種 使用關係
	    大多數情況下依賴關係體現在某個類的方法 使用 另一個類的物件 作為引數。
  
(一)依賴:
1. 概念:是一種使用關係,耦合度最弱。
    類A使用類B的一部分屬性和方法,不會主動改變類B的內容,但是類B的變化會影響到A。
    具有偶然性、臨時性。

2. 體現:
    類B 作為 類A的 成員函式引數。
    類B 作為 類A的 成員函式的區域性變數
    類A的成員函式呼叫的 類B的靜態方法
3. 程式碼:
  
  
被關聯類B 以類的屬性形式出來在關聯類A中。
關聯類A  引用了一個型別為被關聯類B的全域性變數。 

設計模式

 底層設計資訊和頂層架構設計共同組成了整個房屋的架構文件,滿足構建和維護該系統的需求
   The only way to go fast, is to go well.
OCP,Open For Extension Closed For Modification Principle,簡稱開閉原則。開閉原則是指軟體實體是可以擴充套件的,但是不可修改 
         	模組和函式是對擴充套件(提供方)開放的,對修改(使用方)關閉的  
SRP,Single Responsibility Principle,單一職責原則   
DIP,Dependence Inversion Principle,依賴倒置原則。抽象不應該依賴於細節,細節應該依賴於抽象
ISP,Interface Segegation Principle,介面隔離原則。一個介面對外只提供一種功能,不同功能應該透過不同的介面提供,而不是把多種功能都封裝到一個介面中
LSP,Liskov Substitution Principle,里氏替換原則。任何地方出現的抽象類,都可以使用該抽象類的實現類來代替,
CARP,Composite/Aggregate Reuse Principle,優先使用物件組合而不是繼承原則
LOD,Law of Demeter,迪米特法則,也叫做最少知道原則(The Least Knowledge Principle

設計模式---經驗
    第一類是建立型模式 ,該模式通常和物件的建立有關,涉及到物件例項化的方式
       單例模式、工廠模式、抽象工廠模式、建造者模式、原型模式五種;
	第二類是結構型模式,結構型模式描述的是如何組合類和物件來獲得更大的結構
	    代理模式、裝飾者模式、介面卡模式、橋接模式、組合模式、外觀模式、享元模式共7種模式。
    第三種是行為型模式,用來描述對類或物件怎樣互動和怎樣分配職責
        模板模式、命令模式、責任鏈模式、策略模式、中介者模式、
		觀察者模式、備忘錄模式、訪問者模式、狀態模式、直譯器模式、迭代器模式11種模式。
建立型模式主要是將系統所需要的用到的具體類封裝起來,在內部實現這些具體類的建立和結合,並對外隱藏這個過程細節		
    Prototype Pattern,原型模式是一種物件建立型模式,它採取複製原型物件的方法來建立物件的例項		
    		深複製淺複製問題
    單例模式: 一個類只能建立一個例項物件
                    (禁止類的外部訪問建構函式 解決辦法就是把建構函式設定為私有屬性,在類的內部完成例項化物件的建立
    				提供一個全域性訪問點來獲取類內部建立好的物件)
    Simple Factory Pattern,簡單工廠模式
             透過一個專門的類(工廠)來負責建立其他類的例項(具體產品),這些類都有一個共同的抽象類作為基類(抽象產品)。
    factory pattern,工廠模式同樣屬於類的建立型模式,也成為多型工廠模式	
             工廠模式多出了一個抽象工廠角色作為介面,實際的生產工作在具體工廠類中實現	
    Abstract Factory Pattern,抽象工廠模式
            一種為訪問類提供一個建立一組相關或相互依賴物件的介面,且訪問類無須指定所要產品的具體類就能得到同族的不同等級的產品的模式結構
    Bulider Pattern,建造者模式,也叫做生成器模式,是一種物件建立型模式
          	強調的是建造過程,要關注每一個部件的建造方式,以及各個部件的建造邏輯,最終組合出需要的物件
   
結構型模式   
   Proxy Pattern,代理模式 客戶端只有透過Proxy來實現與被代理類的互動,並且在互動過程中 ,代理可以增加其它操作
   Decorator Pattern,裝飾模式,也叫做包裝模式,是結構型模式的一種:裝飾模式的具體實現就是把一些功能封裝在一個個單獨的子類中
   Adapter Pattern 介面卡模式 介面卡模式可以將一個類的介面轉換成客戶希望的另一種形式的介面
   Composite Pattern,組合模式
    Bridge Pattern,橋接模式
	Facade Pattern,外觀模式  Flyweight Pattern,享元模式 享元模式的目的就是使用共享技術來實現大量細粒度物件的複用。
行為型模式
    Template Pattern,模板方法模式 透過子類繼承對抽象演算法進行不同的實現來達到改變演算法行為的目的
	Command Pattern,命令模式,是一種行為型設計模式
	Chain of Responsibility Pattern,CoR責任鏈模式,
	Strategy Pattern,策略模式
	Mediator Pattern,中介者模式
	Observer Pattern,觀察者模式:
	   一種一對多的模式,多個觀察者物件同時監聽一個主題物件,一旦主題物件發生變化,能夠自動通知所有的觀察者物件。
	     它提供了一種關聯物件之間的同步機制,他們之間透過通訊來保持狀態同步。
	Visitor Pattern,訪問者模式
	    把資料結構和作用於資料結構上的操作進行了分離,在不修改已有類的前提下可以增加新的操作,而新增新的操作就相當於新增一個訪問者。
	Memento Pattern,備忘錄模式
	State Pattern,狀態模式:透過改變物件的內部狀態來達到改變物件行為的目的
	interpreter Pattern,直譯器模式
	Iterator Pattern,迭代器模式

架構

--應對複雜系統的方式
 還是宏觀層面的架構,無論是三種程式設計正規化還是微服務架構,它們都在解決一個問題——分離控制和邏輯。
  所謂控制就是對程式流轉的與業務邏輯無關的程式碼或系統的控制(如多執行緒、非同步、服務發現、部署、彈性伸縮等)​,
  所謂邏輯則是實實在在的業務邏輯,是解決使用者問題的邏輯。
  控制和邏輯構成了整體的軟體複雜度,有效地分離控制和邏輯會讓你的系統得到最大的簡化

複雜系統的問題: 需求、環境和技術的不斷變化,涉及的因素和角色眾多,各種因素之間互相關聯
     邊界的選擇取決於你想要了解的資訊和出於何種目的進行考慮
     系統思維--應對問題的複雜性:將問題分解成更小的組成部分的過程,同時意識到每個部分對整個系統的影響
	 系統的工具:要素、連線和目標  全域性、動態、關聯  適應力、自組織、層次性
	           存量、流量和反饋迴路
			   有限理性   時間延遲
    系統論--資訊理論--控制論
    耗散結構論、協同論、突變論稱為“新三論”
	    耗散結構論: 
	    自組織: 是現代非線性科學和非平衡態熱力學: 單元自律 短程通訊 微觀決策
		突變論: 穩定狀態進入不穩定狀態 不穩定狀態進入另一種穩定狀態

記憶體與程式執行中的報錯

 暫存器--堆heap 和棧stack
 stack 棧主要用於儲存函式呼叫時需要的各種資訊,以及函式執行過程中產生的臨時資料。棧的特點是高效的記憶體分配和釋放,但是大小有限,
    函式返回地址-函式的引數-區域性變數
     1. 區域性變數:在函式內部宣告的區域性變數會被儲存在棧上		

純虛擬函式

C++可以透過抽象類(Abstract Class)和純虛擬函式(Pure Virtual Function)來模擬介面的概念‌
      沒有直接提供介面關鍵字
     C++標準庫本身並沒有直接提供像Java或C#那樣的“介面”關鍵字‌。然而,
    抽象類(Abstract Class)
	     C++語言中沒有抽象類的概念 C++中透過純虛擬函式實現抽象類。
	純虛擬函式(Pure Virtual Function)
	   純虛擬函式是沒有函式體的虛擬函式,它強制派生類(子類)實現該函式
	   
	在C++中,這透過建立一個包含純虛擬函式的抽象類來實現。  
       抽象類通常用作基類,派生類繼承它並提供純虛擬函式的實現。	

倉頡程式設計

虛擬機器監視器(Hypervisor)	
	
Hypervisor的型別和特點
    Hypervisor有兩種型別:型別1(裸機)和型別2(宿主機)。型別1 Hypervisor直接執行在硬體之	


定義運算子函式時需要在 func 關鍵字前面新增 operator 修飾符;
  運算子函式的 引數個數需要匹配對應運算子的要求;
  運算子函式只能定義在 class、interface、struct、enum 和 extend 中;
  運算子函式具有例項成員函式的語義,所以禁止使用 static 修飾符;
  運算子函式不能為泛型函式。
eg: public operator func -(): Point {  Point(-x, -y) }

在Java中,運算子是不能被過載的	
  沒有運算子過載,但卻將基礎非常易用的運算子進行了過載
python過載:  __add__(self, other)  _sub__(self, other)  __mul__(self, other)  _truediv__(self, other)  __str__(self):
  繫結(binding)和重繫結(rebinding)

參考

c++類——類與類之間的關係 https://blog.csdn.net/xiaohei07/article/details/131676336	
架構整潔之道
https://github.com/puge-up/programming-cpp/tree/main
https://bbs.huaweicloud.com/blogs/397606
C++編譯器合成預設建構函式的真相  https://bbs.huaweicloud.com/blogs/321795
C++編譯器自動生成的函式  https://www.cnblogs.com/islch/p/16143768.html

相關文章