温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C++类型萃取(分文件管理)

发布时间:2020-09-16 12:50:03 来源:网络 阅读:276 作者:梦T醒 栏目:编程语言

C++类型萃取(分文件管理)类型萃取
类型萃取是基于c++中的模板特化来实现的,是对于模板特化的应用。

以通用的拷贝函数为例

拷贝函数,c++自带的拷贝函数是俗称的浅拷贝,浅拷贝对于一些内置类型而言不会出错,但对于一些自定义类型在拷贝的时候就会出现内存访问错误(中断),想回顾浅拷贝的“同志”可以看https://blog.51cto.com/14233078/2442527
C++类型萃取(分文件管理)1.此方案虽然解决了拷贝问题,但是缺点也很明显,在每一次拷贝数据,都需要遍历一遍,时间复杂度O(1)

#include<iostream>
using namespace std;
#include<string>

template<class T>
void Copy1(T* dst, T* src, size_t size)
{
    memcpy(dst, src, sizeof(T)*size);
}

// 优点:一定不会出错
// 缺陷:O(N)
template<class T>
void Copy2(T* dst, T* src, size_t size)
{
    for (size_t i = 0; i < size; ++i)
        dst[i] = src[i];
}

bool IsPODType(const char* strType)
{
    // 此处可以将所有的内置类型枚举出来
    const char* strTypes[] = { "char", "short", "int", "long", "long long", "float", "double" };
    for (auto e : strTypes)
    {
        if (strcmp(strType, e) == 0)
            return true;
    }

    return false;
}

template<class T>
void Copy(T* dst, T* src, size_t size)
{
    // 通过typeid可以将T的实际类型按照字符串的方式返回
    if (IsPODType(typeid(T).name()))
    {
        // T的类型:内置类型
        memcpy(dst, src, sizeof(T)*size);
    }
    else
    {
        // T的类型:自定义类型---原因:自定义类型中可能会存在浅拷贝
        for (size_t i = 0; i < size; ++i)
            dst[i] = src[i];
    }
}

void TestCopy()
{
    int array1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    int array2[10];
    Copy(array2, array1, 10);

    string s1[3] = { "1111", "2222", "3333" };
    string s2[3];
    Copy(s2, s1, 3);
}

int main()
{
    TestCopy();
    return 0;
}

C语言参与编译的是.c文件,一个.c文件是一个编译单元。
头文件在预处理阶段被展开,即,预处理器看见#include预处理指令的时候,就用相应头文件的内容替换掉这个#include预处理指令(把头文件内容拷贝到.c文件中,然后删除这条#include预处理指令)。
你应该把头文件看出是导出给外部模块使用的接口,里面存放外部模块需要使用的宏定义及函数原型。
在linux下,可以用gcc -E查看预处理之后的文件。
头文件中的函数原型是提供给编译器作为函数原型检查的,对于不是本源文件中的函数,编译过程中并不会产生实际的调用代码(函数调用需要知道确切的函数地址),只是在相应的地方做个标记,表示在这里需要调用某个函数。编译完成产生的是汇编代码。
如上所述,编译产生的汇编代码并不能直接运行,因为外部函数调用的地方还没给予确切的函数地址。这个工作由链接过程完成。链接器会查找其它源文件所产生的汇编代码,进而找到正确的函数调用地址,然后用这个地址替换掉在编译时做的标记。完成这一步后,程序就可以实际运行了。
因此,.h是根本不会被编译的,它如果被包含,则会被预处理器将其内容一分不差的拷贝到.c文件中,.编译器编译的是拷贝后的这个.c文件。

2.分文件管理:
因为头文件在预处理阶段就已完成,所以不会降低代码效率,因此解决1中代码效率低的问题

头文件

#pragma once

#include<iostream>
using namespace std;
#include<string>

//来自自定义类型
struct TrueType
{};

// 对应自定义类型
struct FalseType
{};

//隐示实例化
template<class T>
struct TypeTraits
{
    typedef FalseType PODTYPE;  // plain old data
};

//显示实例化
template<>
struct TypeTraits<char>
{
    typedef TrueType PODTYPE;
};

template<>
struct TypeTraits<short>
{
    typedef TrueType PODTYPE;
};

template<>
struct TypeTraits<int>
{
    typedef TrueType PODTYPE;
};
template<>
struct TypeTraits<long>
{
    typedef TrueType PODTYPE;
};

template<>
struct TypeTraits<long long>
{
    typedef TrueType PODTYPE;
};

template<>
struct TypeTraits<float>
{
    typedef TrueType PODTYPE;
};

template<>
struct TypeTraits<double>
{
    typedef TrueType PODTYPE;
};

void TestCopy();

源代码

#include"Type_extraction.h"

template<class T>
void Copy(T* dst, T* src, size_t size, TrueType)
{
    // T的类型:内置类型
    memcpy(dst, src, sizeof(T)*size);
}

template<class T>
void Copy(T* dst, T* src, size_t size, FalseType)
{
    // T的类型:自定义类型---原因:自定义类型中可能会存在浅拷贝
    for (size_t i = 0; i < size; ++i)
        dst[i] = src[i];
}

template<class T>
void Copy(T* dst, T* src, size_t size)
{
    Copy(dst, src, size, TypeTraits<T>::PODTYPE());
}

void TestCopy()
{
    int array1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    int array2[10];
    Copy(array2, array1, 10);

    string s1[3] = { "1111", "2222", "3333" };
    string s2[3];
    Copy(s2, s1, 3);
}

测试文件main.c

#include"Type_extraction.h"

int main()
{
    TestCopy();
    return 0;
}

模板的声明和定义必须放在一个文件原因
https://blog.csdn.net/chigusakawada/article/details/78752668
显示实例化,隐式实例化概念
https://blog.csdn.net/qiujianjian/article/details/84792608

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI