一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - C++元編程語言初步入門詳解

C++元編程語言初步入門詳解

2022-02-10 15:40微小冷 C/C++

這篇文章主要為大家介紹了C++元編程語言初步入門的詳解示例,文中包含詳細的基本概念及運用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助

模板

由于模板元編程需要以面向對象為基礎,所以如有疑問之處可以先補充一點C++面向對象的知識:

C++面向對象這一篇就夠了

泛型初步

由于C++是靜態強類型語言,所以變量一經創建,則類型不得更改。如果我們希望創建一種應用廣泛地復數類型,那么相應地需要基于intfloatdouble這些基礎類型逐一創建,十分麻煩。泛型編程便是為了簡化這一過程而生。

能夠容納不同數據類型作為成員的類被成為模板類,其基本方法為在類聲明的上面加上一行模板聲明代碼

template<typename T>,下一行為class myClass,其調用過程為myClass<T> m。

列舉案例如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>
using namespace std;
template<typename C>
struct Abstract{
    C real;         //real為C類型
    C im;
    Abstract(C inReal, C inIm){
        real = inReal;
        im = inIm;
    }
    void printVal(){
        cout<<"Abstract:"<<real<<"+"<<im<<"i"<<endl;
    };
    Abstract& multi(Abstract val){
        C temp = real*val.real - im*val.im;
        im = real*val.real + im*val.im;
        real = temp;
        return *this;
    };
};
int main(){
    Abstract<float> fTemp{1,2};//C類型為float
    fTemp.multi(fTemp);
    fTemp.printVal();
    system("pause");
    return 0;
}

函數模板

當然,上述multi并不能實現兩個不同類型的Abstract之間的相乘,所以可以將multi函數改為

?
1
2
3
4
5
6
7
template<typename T>
Abstract<C>& multi(Abstract<T> val){
    C temp = real*val.real - im*val.im;
    im = real*val.real + im*val.im;
    real = temp;
    return *this;
}

這樣就能夠實現如下功能。

?
1
2
3
4
5
6
7
8
9
int main(){
    Abstract<float> fTemp{1,2};
    Abstract<int> iTemp{1,2};
    fTemp.multi(iTemp);
    fTemp.printVal();
    getReal(fTemp);
    system("pause");
    return 0;
}

友元

模板類具備一部分普通類的性質,比如struct和class的區別,public、protected、private的性質,以及友元等。模板的聲明特性也可以應用在函數中,例如

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
using namespace std;
template<typename C>
class Abstract{
    C real;
    C im;
public:
    Abstract(C inReal, C inIm){
        real = inReal;
        im = inIm;
    }
    void printVal(){
        cout<<"Abstract:"<<real<<"+"<<im<<"i"<<endl;
    };
    Abstract& multi(Abstract val){
        C temp = real*val.real - im*val.im;
        im = real*val.real + im*val.im;
        real = temp;
        return *this;
    }
    template<typename T> friend void getReal(Abstract<T> num);  //聲明友元
};
template<typename C>
void getReal(Abstract<C> num){
    cout<<num.real<<endl;
}
int main(){
    Abstract<float> fTemp{1,2};
    fTemp.multi(fTemp);
    fTemp.printVal();
    getReal(fTemp);
    system("pause");
    return 0;
}

需要注意的一點是,在模板類中聲明友元,其前綴<typename T>中的類型標識不得與已有的類型標識重復,否則編譯無法通過。

由于函數模板可以針對不同的數據類型進行求解操作,是對函數或者方法實例的抽象,所以又被稱為算法。

模板參數

如果將模板理解為一種類型聲明的函數,那么模板也應該具備一些函數具備的功能。首先其模板參數中可以包含實際類型參數,例如

?
1
2
template<typename T, int max>
class Test{}

其調用時可以寫為

?
1
Test<int,256> pixel;

模板同樣支持默認參數,即可以實現如下形式

?
1
2
3
template<typename T=int, int max=256>
class Test{}
Test pixle;

除了數據類型、值之外,模板本身也可以作為模板參數,例如下面的形式是合法的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<typename T, template<typename> class C>
struct Test{
    C<T>* val;
    Test(C<T>* inVal){
        val = inVal;
    }
};
int main(){
    Abstract<int> fTemp{1,2};
    Test<int,Abstract> test(&fTemp);
    test.val->printVal();
    system("pause");
    return 0;
}

其結果為

?
1
2
3
4
PS E:\Code\cpp> g++ .\generic.cpp
PS E:\Code\cpp> .\a.exe
Abstract:1+2i
請按任意鍵繼續. . .

需要注意的一點是,在模板類中定義的模板類,需要進行實例化,否則會出現錯誤,所以在Test中,以指針形式創建了模板類。

類型函數

以數據類型為輸入或輸出的函數即為類型函數,在C語言中,sizeof便是一種類型函數,其輸入為數據類型,輸出為數據類型所需要的內存空間。

在C++11中,using可以實現數據類型賦予的功能,其使用方法與typedef相似

?
1
2
3
4
template<typename T>
struct Test{
    using type = T;
}

元編程的基本概念

元編程是泛型編程的一個超集,兩者的本質均是針對不同數據類型的算法,后者則更關注傳入參數的廣泛性。如果將元編程分為四個層次

  • 無計算
  • 運算符連接的運算
  • 編譯時具備選擇等非遞歸計算
  • 編譯時具備遞歸運算

那么泛型編程可以作為第一類元編程,或者說更加關注的是參數的傳入傳出過程,而元編程則更關注不同數據類型的選擇過程。

例如,我們可以實現一個最多包含三個元素的元組Tuple,其思路為,三元元素可以看成是一個二元元組與一個參數的組合;二元元組可以看成是一元元組與參數的組合;一元元組則是一個基本數據類型的變量。在這個元組的實現過程中,除了賦值過程實現泛型之外,也需要判斷當前所實現的元組元素個數,如果其初始化參量為3個時,需要遞歸式地創建變量,直到賦值參數為1個。則其實現如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class Nil{};
//主模板
template<typename T1=Nil, typename T2=Nil, typename T3=Nil>
struct Tuple : Tuple<T2,T3>{
    T1 x;
    using Base = Tuple<T2,T3>;      //三元元組以二元元組為基礎
    //返回值為Tuple<T2,T3>指針類型的base()函數
    //static_cast將this轉化為Base*類型
    Base* base(){return static_cast<Base*>(this);}
    const Base* base() const {return static_cast<const Base*>(this);}
    //構造函數繼承二元元組,在構造本類中x的同時,構造基類Tuple<T2,T3>
    Tuple(const T1& t1, const T2& t2, const T3& t3)
        :Base{t2,t3},x{t1}{}
};
template<typename T1>
struct Tuple<T1>{
    T1 x;
};
template<typename T1, typename T2>
struct Tuple<T1,T2> : Tuple<T2>{
    T1 x;
    using Base = Tuple<T2>;
    Base* base(){return static_cast<const Base*>(this);}
    const Base* base() const {return static_cast<const Base*>(this);}
    Tuple(const T1& t1,const T2& t2):Base{t2}, x{t1}{}
};
template<typename T1, typename T2, typename T3>
void print_elements(ostream& os, const Tuple<T1,T2,T3>& t){
    os<<t.x<<",";
    print_elements(os,*t.base());
}
template<typename T1, typename T2>
void print_elements(ostream& os, const Tuple<T1,T2>& t){
    os<<t.x<<",";
    print_elements(os,*t.base());
}
template<typename T1>
void print_elements(ostream& os, const Tuple<T1>& t){
    os<<t.x;
}
//運算符重載
template<typename T1, typename T2, typename T3>
ostream& operator<<(ostream& os, const Tuple<T1,T2,T3>& t){
    os<<"{";
    print_elements(os,t);
    os<<"}";
    return os;
}
int main(){
    Tuple<int,double,char> x{1,2.5,'a'};
    cout<<x<<endl;
    system("pause");
    return 0;
}

其輸出結果為

?
1
2
3
PS E:\Code\cpp> g++ .\generic.cpp
PS E:\Code\cpp> .\a.exe
{1,2.5,a}

可變參數模板

上述實現過程非常繁瑣,而且限制了元組中的元素個數,如果標準庫中用上述的書寫風格,那么標準庫除了這個元組之外也寫不了其他的東西了。好在C++模板提供了可變參數的功能,例如,我們可以先將打印模板函數寫為

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//typename... T 代表可變參數
template<typename T1, typename... T>
void print_elements(ostream& os, const Tuple<T1,T...>& t){
    os<<t.x<<",";
    print_elements(os,*t.base());
}
template<typename T1>
void print_elements(ostream& os, const Tuple<T1>& t){
    os<<t.x;
}
template<typename... T>
ostream& operator<<(ostream& os, const Tuple<T...>& t){
    os<<"{";
    print_elements(os,t);
    os<<"}";
    return os;
}

其輸出結果為

?
1
2
3
4
PS E:\Code\cpp> g++ .\generic.cpp
PS E:\Code\cpp> .\a.exe
{1,2.5,a}
請按任意鍵繼續. . .

然后將Tuple也做相同的更改

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template<typename T1, typename... T>
struct Tuple : Tuple<T...>{
    T1 x;
    using Base = Tuple<T...>;      //N+1元元組以N元元組為基
    Base* base(){return static_cast<Base*>(this);}
    const Base* base() const {return static_cast<const Base*>(this);}
    //注意T&...的書寫格式
    Tuple(const T1& t1, const T&... t):Base{t...},x{t1}{}
};
template<typename T>
struct Tuple<T>{
    T x;
};
/*
    print模板
*/
int main(){
    Tuple<string, double,int,char> tt("hello",1.5,1,'a');
    cout<<tt<<endl;
    system("pause");
    return 0;
}

其輸出結果為

?
1
2
3
PS E:\Code\cpp> g++ .\generic.cpp
PS E:\Code\cpp> .\a.exe
{hello,1.5,1,a}

以上就是C++元編程語言初步入門詳解的詳細內容,更多關于C++元編程語言初步的資料請關注服務器之家其它相關文章!

原文鏈接:https://blog.csdn.net/m0_37816922/article/details/103781346

延伸 · 閱讀

精彩推薦
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
主站蜘蛛池模板: 国产成人亚洲影视在线 | 操男孩| 国产伦精一区二区三区视频 | 娇小老少配xxxxx性视频 | 国产色拍| 婷婷日日夜夜 | 97porm自拍视频区原创 | 韩国三级在线高速影院 | 亚洲AV久久无码精品九九软件 | 五月婷婷在线观看 | 毛片群| 特黄未满14周岁毛片 | 男女车车好快的车车免费网站 | 男人午夜禁片在线观看 | 成人影院免费在线观看 | 白发在线视频播放观看免费 | 国产理论片在线观看 | 国产福利你懂的 | 97超pen个人视频公开视频视 | 女主被男主做哭失禁高h | 青草国产在线观看 | 17岁韩国在线观看免费1 | 高清一区高清二区视频 | 98成人 | 欧美视频黑鬼大战白妞 | 美女福利网站 | 三级全黄的视频 | 欧美高清乌克兰精品另类 | 国产一区二区播放 | miaa076深田咏美在线 | 国产一级视频在线观看 | 黄瓜视频黄版 | 精品亚洲视频在线观看 | 91亚洲精品丁香在线观看 | 动漫人物差差插曲漫画 | 亚洲精品第一国产综合高清 | 114毛片免费观看网站 | 日本高清免费观看 | 亚洲九九精品 | 久久国产精品永久免费网站 | 亚洲精选在线观看 |