c++柔性數組、友元、類模版

目錄

1、柔性數組:?

?2、友元函數:

3、靜態成員?

注意事項

面試題:c/c++ static的作用?

C語言:

C++:

為什么可以創建出?objx

4、對象與對象之間的關系

5、類模版


1、柔性數組:?

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>using namespace std;class MyString
{
private:struct  StrNode{int refcount; //引用計數int slen;int capa;char data[0]; //數組不填或填0就成為柔性數組};private:StrNode* pstr;static const size_t DAFAUSIZE = 32;static const size_t INCSIZE = 2;static StrNode* GetMem(rsize_t n){size_t total = (n > DAFAUSIZE) ? n + 1 : DAFAUSIZE;StrNode* s = (StrNode*)malloc(sizeof(StrNode) + sizeof(char) * total);memset(s, 0, sizeof(StrNode) + sizeof(char) * total);s->capa = total - 1;return s;}static void  FreeMem(StrNode *p){free(p);}
public:MyString(const char* p = nullptr) :pstr(nullptr){if (p != nullptr){int len = strlen(p);pstr = GetMem(len);pstr->refcount = 1;pstr->slen = len;strcpy(pstr->data, p);}}MyString(const MyString &st) :pstr(st.pstr)  //st給當前對象{if (pstr != nullptr){pstr->refcount += 1; //+1 說明有兩個對象持有這塊空間}}MyString(MyString &&st) :pstr(st.pstr)  //移動構造{st.pstr = nullptr;}~MyString() {if (pstr != nullptr && --pstr->refcount == 0){FreeMem(pstr);}pstr = nullptr;}ostream& operator<<(ostream& out)const{if (pstr != nullptr){out << pstr->data;}return out;}
};
ostream &operator<<(ostream &out, const MyString &st)
{return st << out;
}int main()
{MyString s1 = "chengxi";MyString s2(s1);MyString s3(s2);MyString s4(s3);cout << s3 << endl;return 0;
}

?2、友元函數:

(1)不具有傳遞特性、繼承特性、是單向的。

(2)友元函數分為:函數友元、成員函數友元、類友元

(3)友元函數是訪問類的對象非公有屬性。

成員函數友元:

using namespace std;
class Base;
class Test
{
private:int sum;
public:Test(int x = 0) :sum(x) {}void SetSum(int x = 0){sum = x;}int GetSum()const { return sum; }int Add(const Base &it);
};class Base
{friend int Test::Add(const Base& it);//成員函數友元int num;
public:Base(int x = 0) :num(x){}
};
int Test::Add(const Base& it)
{return this->sum + it.num;
}int main()
{Test t1(100);Base b1(2);t1.Add(b1);
}

類友元:?

using namespace std;
//Test對象訪問base的私有和公有,注意方向
class Base
{friend class Test; 
private:int num;
public:Base(int x = 0) :num(x){}
};class Test
{
private:int sum;
public:Test(int x = 0) :sum(x) {}void SetSum(int x = 0){	sum = x;}int GetSum()const { return sum; }int Add(const Base &it) {return it.num + 10;}int func(const Base& it){return it.num;}
};int main()
{Test t1;Base b1;t1.Add(b1);t1.func(b1);return 0;
}

3、靜態成員?

(1) 類靜態成員只能在類外進行初始化,

(2)靜態成員變量在數據區存儲。靜態量不屬于對象,是被所有對象共享,不管有多少個對象,靜態成員只有一份存在于數據區。

(3)靜態數據可以在普通方法中使用

(4)為什么不能在參數列表中對靜態成員初始化?

答:參數列表,在定義對象的時候要調用構造函數,拿參數列表對數據成員進行創建,靜態成員被所有對象共享,在定義不同的對象時都要對靜態成員進行構建,c++中,數據成員(對象、變量)在生存期內只能被構建一次。放在參數列表中,被構建了n次,不允許。要在類外進行初始化。

靜態成員在類模版中,數據類型不同?,就會產生不同的 “靜態成員”

using namespace std;template<class T>
class Object
{
private:int value;
protected:static int num;
public:Object(int x=0):value(x){}~Object(){}
};class Test :public Object<Test>
{
public:Test(){cout << "Create Test::" << (num += 1) << endl;}
};class Base :public Object<Base>
{
public:Base() {cout << "Create Base:" << (num += 1) << endl;}
};
template<class T>
int Object<T>::num = 0;
int main() {Test t1[1];Base b1[2];return 0;
}

  • Test t1[1];:創建一個包含 1 個?Test?對象的數組,在創建?Test?對象時,會調用?Test?類的構造函數,輸出相應的信息。
  • Base b1[2];:創建一個包含 2 個?Base?對象的數組,在創建?Base?對象時,會調用?Base?類的構造函數,輸出相應的信息。

注意事項

由于?Object?類的靜態成員變量?num?是模板化的,Object<Test>?和?Object<Base>?是不同的模板實例化,它們各自擁有獨立的?num?副本。所以在創建?Test?和?Base?對象時,它們的?num?計數是相互獨立的。

面試題

C語言:

(1)靜態關鍵字修飾全局/局部變量,存在于數據區,當函數消亡時,靜態變量還存在,可以&。

全局變量有static和無的區別?

(2)全局靜態變量只在本文件中可見,同一工程的其他文件不可見, (私有),未用static修飾的全局變量,可以用extern在其他文件用。

(3)static修飾函數,此函數只在當前文件夾有效,在其他文件中不能用,(私有)。修飾函數本身而不是修飾返回值 static int* add() {} ,。

C++:
(1)static可以修飾類的成員,要在類外進行初始化。所有的對象都共享同一個靜態成員變量,派生的類也共享(但前提是將其設置成protected?/public)。

(2)靜態成員變量不屬于對象,無this,在常方法中可以修改靜態成員變量的值,this不修飾它。

static可以修飾屬性的類型,要在類外進行初始化,如果是靜態常性變量可以在類內進行初始化,但必須要求是整型類型。

(3)static修飾成員方法,static void func(){}? 無this指針。靜態成員方法無this。

(3)static修飾的成員方法可以訪問靜態屬性也可以訪問非靜態屬性(非靜態屬性必須把對象傳進來)。

靜態成員方法可以通過 對象訪問,也可以通過類名。

靜態成員變量
  • 類的所有對象共享:靜態成員變量屬于類本身,而不是類的某個對象。無論創建多少個類的對象,靜態成員變量都只有一份副本,被所有對象共享。
  • 需要在類外初始化:靜態成員變量必須在類外進行初始化,因為它不依賴于對象的創建。

    ?:obja可以創建出來,指針:4字節

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    class Object
    {
    private:int value;
    private:static Object objx;
    private:Object(int x = 0) :value(x) {cout << "create Obj" << this << endl;}~Object(){cout << "destroy obj:" << this << endl;}
    };
    Object Object::objx(1);int main()
    {return 0;
    }

    • 成員變量
      • int value;:一個私有成員變量,用于存儲對象的值。
      • static Object objx;:一個私有靜態成員變量,類型為?Object?類本身。靜態成員變量屬于類,而不是類的某個對象,所有該類的對象共享同一個靜態成員變量。
    • 靜態成員變量初始化
      • Object Object::objx(1);
        

        這行代碼對?Object?類的靜態成員變量?objx?進行初始化,調用了?Object?類的構造函數,并將參數?1?傳遞給構造函數,將?value?成員變量初始化為?1

        為什么可以創建出?objx

        雖然?Object?類的構造函數和析構函數都是私有的,通常情況下,外部代碼無法直接創建?Object?類的對象。但是,靜態成員變量?objx?是類的一部分,類的內部可以訪問其私有成員。因此,在類的外部對靜態成員變量?objx?進行初始化時,實際上是在類的作用域內調用了構造函數,這是被允許的。

        ?

        當程序開始執行時,在進入?main?函數之前,會先對靜態成員變量進行初始化,所以?Object::objx?會被創建,調用構造函數輸出創建信息。當程序結束時,靜態對象?objx?會被銷毀,調用析構函數輸出銷毀信息。

    using namespace std;
    class Object
    {
    private:int value;
    private:static Object objx;
    private:Object(int x = 0) :value(x) {cout << "create Obj" << this << endl;}~Object(){cout << "destroy obj:" << this << endl;}
    public:void Print()const { cout << "value" << value << endl; }void SetValue(int x) { value = x; }int GetValue()const { return value; }//通過靜態方法將靜態對象的地址返回static Object* getObject(){return &objx;}
    };
    Object Object::objx(1);int main()
    {Object* pa = Object::getObject();Object* pb = Object::getObject();if (pa == pb) { cout << "pa,pb pinter:object" << endl; }pa->Print();pa->SetValue(100);pa->GetValue();pa->Print();return 0;
    }
    • if (pa == pb) { cout << "pa,pb pinter:object" << endl; }:比較?pa?和?pb?的值,如果相等,說明它們指向同一個對象,輸出相應信息。由于?objx?是靜態對象,無論調用多少次?getObject()?函數,返回的都是同一個對象的地址,所以?pa?和?pb?相等。
    • 通過靜態成員函數可以在類外部訪問私有靜態成員對象,并且由于靜態成員對象只有一個實例,無論通過多少個指針訪問,操作的都是同一個對象。

    4、對象與對象之間的關系

    依賴關系:用-------> 表示

    一個對象在運行期間會用到另一個對象的關系,通常在運行期間產生,并且伴隨運行時的變化依賴關系也發生變化。主要表現為 :“使用關系”。

    關聯關系:用——> 表示:

    靜態關系,如:學生和學校,是關聯關系

    在設計中。關聯關系主要體現在目標類型的指針或引用。

    聚合、繼承、組合等。

    5、類模版

    template<類型模版參數表>

    類模板不是類,因此無法直接實例化對象,需要在聲明類時給定確定的數據類型,編譯器才會以此分配內存。對于普通類而言,類的聲明和類成員函數的定義可以寫在不同的文件中,但是對于類模板來說,最好定義在同一個文件中。

    //define _N 10
    template<class T,int N>
    class SeqStack
    {T* data;int capa;int top;static const int stackinitsize = 100;static const int incsize = 2;static T* GetMen(size_t sz){T* newdata = (T*)malloc(sizeof(T) * sz);if (nullptr == newdata){cout << "malloc fail" << endl;exit(1);}memset(newdata, 0, sizeof(T) * sz);return newdata;}static void FreeMem(T* p){free(p);}public:SeqStack(int sz = stackinitsize) :data(nullptr), capa(sz), top(-1){//data = (T*)malloc(sizeof(T) * capa); //只申請空間不構建對象data = GetMen(capa);}~SeqStack(){}int size()const { return top + 1; }bool empty()const { return size() == 0; }int capacity()const { return capa; }bool full()const { return size() == capacity(); }bool push(const T& x){if (full())return false; //滿了調增容函數 top += 1;new(&data[top]) T(x);   //data[++top] = x;構建對象return true;}bool gettop(T *val) {if (empty())return false;val = data[top];return true;}bool poptop(T& val){if (empty())return false;val = data[top];(&data[top])->~T(); //析構top中的對象top -= 1;return true;}bool pop(){if (empty())return false;(&data[top])->T();top -= -1;return true;}};
    int main()
    {SeqStack<int, 10> istack;   //using T:int N:10}
    int main() {ClassName<int> intObj(10);  // 實例化類模板,創建一個處理 int 類型的類對象int result = intObj.getData();std::cout << "Result: " << result << std::endl;ClassName<double> doubleObj(3.14);  // 實例化類模板,創建一個處理 double 類型的類對象double dResult = doubleObj.getData();std::cout << "Result: " << dResult << std::endl;return 0;
    }

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

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

    相關文章

    主相機綁定小地圖

    資源初始化&#xff1a;在類中通過 property 裝飾器定義主相機、小地圖相機、小地圖精靈等資源屬性&#xff0c;便于在編輯器中賦值。在 start 方法里&#xff0c;當確認這些資源存在后&#xff0c;創建渲染紋理并設置其大小&#xff0c;將渲染紋理與小地圖相機關聯&#xff0c…

    linux-core分析-柔性數組越界訪問

    文章目錄 core的調用棧core分析修改修改原因柔性數組定義代碼修改總結core的調用棧 vocb core 崩潰:core的大小都是573M左右 Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000007f789af0d0 in strlen () from /lib/libc.so.6[Current thread is 1 (LW…

    leetcode 代碼隨想錄 數組-區間和

    題目 給定一個整數數組 Array&#xff0c;請計算該數組在每個指定區間內元素的總和。 輸入&#xff1a; 第一行輸入&#xff1a;為整數數組 Array 的長度 n&#xff0c;接下來 n 行&#xff0c;每行一個整數&#xff0c;表示數組的元素。隨后的輸入為需要計算總和的區間&…

    部署nerdctl工具

    nerdctl 是一個專為Containerd設計的容器管理命令行工具&#xff0c;旨在提供類似 Docker 的用戶體驗&#xff0c;同時支持 Containerd 的高級特性&#xff08;如命名空間、compose等&#xff09;。 1、下載安裝 wget https://github.com/containerd/nerdctl/releases/downlo…

    【論文筆記】DeepSeek-R1 技術報告

    最強開源LLM&#xff0c;性能和效果都很棒&#xff1b;在數學、代碼這種有標準正確答案的場景&#xff0c;表現尤為突出&#xff1b;一些其他場景的效果&#xff0c;可能不如DeepSeek-V3和Qwen。 Deepseek-R1沒有使用傳統的有監督微調sft方法來優化模型&#xff0c;而使用了大規…

    YOLO學習筆記 | 基于YOLOv5的車輛行人重識別算法研究(附matlab代碼)

    基于YOLOv5的車輛行人重識別算法研究 ???????????????????????????? 摘要 本文提出了一種基于YOLOv5的車輛行人重識別(ReID)算法,結合目標檢測與特征匹配技術,實現高效的多目標跟蹤與識別。通過引入注意力機制、優化損失函數和輕量化網絡結構…

    Buildroot與Yocto介紹比對

    Buildroot 和 Yocto 是嵌入式 Linux 領域最常用的兩大系統構建工具&#xff0c;它們在功能定位、使用方法和適用場景上有顯著差異。以下從專業角度對兩者進行對比分析&#xff1a; 一、Buildroot 核心功能與特點 1. 功能定位 輕量級系統構建工具&#xff1a;專注于快速生成精…

    VUE3初始化項目安裝

    本次就是作為實驗使用&#xff0c;包括安裝過程中遇到的問題&#xff0c;供大家提供參考&#xff0c;話不多說&#xff0c;看過程&#xff1a; 第1步&#xff1a;首先分別安裝node.js和npm&#xff0c;這步網上有很多資料&#xff0c;很簡單&#xff0c;過程省略了&#xff0c…

    GO語言學習(17)Gorm的數據庫操作

    目錄 &#x1f3c6;前言 1.Gorm的簡介 2.GORM連接數據庫 2.1 配置DSN Mysql&#xff0c;TiDB&#xff0c;MariaDB PostgreSQL SQL Server SQLite 2.2 gorm.Open連接數據庫 3.數據庫連接池的配置 4.使用GORM對數據庫進行操作&#xff08;重點&#xff09; 4.1 創…

    【JavaEE】網絡原理詳解

    1.????前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 親愛的朋友們&#x1f44b;&#x1f44b;&#xff0c;這里是E綿綿呀????。 如果你喜歡這篇文章&#xff0c;請別吝嗇你的點贊????和收藏&#x1f4d6;&#x1f4d6;。如果你對我的…

    第十五屆藍橋杯單片機省賽程序設計試題

    同時也是積分賽——測量NE555輸出脈沖頻率 第十五屆 藍橋杯 單片機設計與開發項目 省賽1 第二部分 程序設計試題&#xff08;85 分&#xff09; &#xff08;大學組&#xff09; 一 基本要求 1、使用大賽組委會統一提供的四梯單片機競賽實訓平臺&#xff0c;完成本試題程序…

    JavaScript智能對話機器人——企業知識庫自動化

    引言 內部知識管理常面臨信息分散、查找困難的問題。本文將使用Node.js和虎躍辦公的智能對話API&#xff0c;構建企業級知識問答機器人&#xff0c;支持自然語言查詢和自動學習。 核心技術 自然語言處理&#xff08;NLP&#xff09;意圖識別機器學習模型微調REST API集成 代…

    元宇宙浪潮下,前端開發如何“乘風破浪”?

    一、元宇宙對前端開發的新要求 元宇宙的興起&#xff0c;為前端開發領域帶來了全新的挑戰與機遇。元宇宙作為一個高度集成、多維互動的虛擬世界&#xff0c;要求前端開發不僅具備傳統網頁開發的能力&#xff0c;還需要掌握虛擬現實&#xff08;VR&#xff09;、增強現實&#…

    Spring Boot 3.4.3 基于 Caffeine 實現本地緩存

    在現代企業級應用中,緩存是提升系統性能和響應速度的關鍵技術。通過減少數據庫查詢或復雜計算的頻率,緩存可以顯著優化用戶體驗。Spring Boot 3.4.3 提供了強大的緩存抽象支持,而 Caffeine 作為一款高性能的本地緩存庫,因其優異的吞吐量和靈活的配置,成為許多開發者的首選…

    QT Quick(C++)跨平臺應用程序項目實戰教程 6 — 彈出框

    目錄 1. Popup組件介紹 2. 使用 上一章內容完成了音樂播放器程序的基本界面框架設計。本小節完成一個簡單的功能。單擊該播放器頂部菜單欄的“關于”按鈕&#xff0c;彈出該程序的相關版本信息。我們將使用Qt Quick的Popup組件來實現。 1. Popup組件介紹 Qt 中的 Popup 組件…

    DuckDB系列教程:如何分析Parquet文件

    Parquet 是一種強大的、基于列的存儲格式&#xff0c;適用于實現更快捷和更高效的數據分析。您可以使用 DuckDB 這種內存型分析數據庫來處理 Parquet 文件并運行查詢以對其進行分析。 在這篇文章中&#xff0c;我們將逐步介紹如何使用 DuckDB 對存儲在 Parquet 文件中的餐廳訂單…

    異步框架使用loguru和contextvars實現日志按Id輸出

    需求闡述 工作中使用fastStream模塊消費kafka事件的時候&#xff0c;遇到以下問題。1. 由于main.py模塊要用到許多其他模塊 &#xff0c;main模塊&#xff0c;和其他模塊都有日志輸出。2. 要實現異步消費事件&#xff0c;但是又不希望日志打印的很亂。3. 想著在每次消費事件的…

    【HTTPS協議】

    文章目錄 一、HTTPS二、HTTPS協議五種加密方案1.只使用對稱加密2.只使用非對稱加密3.雙方都使用非對稱加密4.對稱加密非對稱加密中間人攻擊理解數字簽名CA機構和證書 5. 對稱加密非對稱加密證書認證中間人篡改證書&#xff1f;中間人調包整個證書&#xff1f; 常見問題總結 一、…

    算法設計學習8

    實驗目的及要求&#xff1a; 通過深入學習樹&#xff08;Tree&#xff09;和二叉樹&#xff08;Binary Tree&#xff09;這兩種重要的數據結構&#xff0c;掌握它們的基本概念、性質和操作&#xff0c;提高對樹形結構的理解和應用能力。通過本實驗&#xff0c;學生將深化對樹和…

    P17_ResNeXt-50

    &#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 一、模型結構 ResNeXt-50由多個殘差塊&#xff08;Residual Block&#xff09;組成&#xff0c;每個殘差塊包含三個卷積層。以下是模型的主要結構&#xff1…