CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛

泛型方法的定义和使用c#(速看)c泛型方法,C|泛型机制:预编译指令define、泛型指针与共用体,

1.c++ 泛型实现原理

C++通过模板支持泛型机制,C没有模板语法机制,通过预编译指令#define、泛型指针与共用体来实现一定程度上的泛型机制1 预编译指令#define#define宏的参数没有类型限制,可以用此来作为泛型编程。

2.c实现泛型

宏与类型无关只要对参数的操作是合法的,它可以使用于任何参数类型#define TYPE int#define SQUARE(x) ((x)*(x))TYPE square(TYPE x){ return

3.泛型方法必须定义在泛型类中

x*x; } #define PRINT(FORMAT, VALUE) \ printf(“The value of “#VALUE \” is ” FORMAT “\n”, VALUE) void

4.简述c#中泛型的主要思想,使用泛型有什么好处

test(){ int x = 4; PRINT(“%d”,x+3); } #define MAX(a, b) ((a) > (b) ? (a) : (b))带参宏和函数的不同之处:

5.C#泛型的作用

2 泛型指针void*对于高级编程语言而言,数据必须具有类型的属性,类型决定其存储单元的字节数,及与类型相关的编码与解码方式void表示“空、无”,是C或C++的关键字:voidtest(void){

6.泛型是什么,C++泛型编程又是什么?

// 这里的void表示”无”//void var; // error illegal use of type voidvoid * p; // 指针提供一个存储单元的蓝图,并提供首地址,需要类型决定存储单元的字节数,及编码解码方式,

7.泛型方法只能出现在泛型类、泛型结构或者泛型接口中

// 允许声明指针目标暂定为void(无类型),但最终解引用到值时,需要提供类型void **pp; p = *pp; int val=5; p = &val; //int a = *p; // illegal indirection

8.泛型方法和泛型类

int b = *(int *)p; // 类型未确定,即无法确定对应内存空间的长度和解码方案,// 强制类型转换,即重新确定长度和解码方案constint c = 6; constvoid

9.c#中泛型定义

*cp = &c; }在C中指针变量拥有与其他变量一样的类型之所以指针变量会有类型是因为当我们想解引用指针变量目标对象的值时, 编译器已经知道指针所指向的目标对象的数据的类型, 从而可以访间相应的数据。

10.C++泛型函数

但是, 有些时候我们在数据处理的某一阶段并不关心指针所指向的目标对象的具体类型在这种情况下,就可以使用泛型指针(generic pointer),泛型指针并不指定具体的数据类型C语言中的指针可以分为三类:指向数据对象的指针、指向函数的指针和指向“虚无”的指针(void *类型)。

对它们可以进行的运算完全不同对指向数据对象的指针可以进行*(间接访问)、+、-等运算;指向函数的指针则只有一元*运算,而不存在+、-等运算;至于指向void 类型的指针,*(间接访问)、+、-等几种运算都没有定义。

指向数据对象的指针可能勉强而不精确地称为“变量的地址”,其他两种指针都跟变量没有什么关系通常情况下,C只允许相同类型的指针之间进行转换例如:一个字符型指针sptr (个字符串)和一个整型指针iptr, 我们不允许把sptr转换为iptr或把iptr转换为sptr。

但是,泛型指针能够转换为任何类型的指针, 反之亦然因此, 如果有一个泛型指针gptr, 就可以把sptr转换为gptr或者把gptr转换为sptr在C语言中, 通常声明一个void指针来表示泛型指针void通常用于表示类型暂定,对于强类型语言,为了实现一些运算符或函数的通用性,通常首先将类型表示为void,最终类型转换为具体类型。

如malloc()、new、qsort()等2.1 泛型指针通常用做库函数或自定义函数参数.很多情况下void指针都是非常有用的例如,C标准函数库中的memcpy函数, 它将一段数据从内存中的一个地方复制到另一个地方。

由于memcpy可能用来复制任何类型的数据,因此将它的指针参数设定为void指针是非常合理的void指针同样也可以用到其他普通的函数中例如交换函数swap2(),可以把函数参数改为vvoid指针,这样,swap2()就变成一个可以交换任何类型数据的通用交换函数, 代码如下:。

#include#include#includeintswap2(void *x, void *y, int size){ void *tmp;

if((tmp=malloc(size)) == NULL) return-1; memcpy(tmp,x,size); memcpy(x,y,size); memcpy

(y,tmp,size); free(tmp); return0; } intmain(){ int a=3,b=4; swap2(&a,&b,sizeof(int));

printf(“%d %d\n”,a,b); double c=3,d=4; swap2(&c,&d,sizeof(double)); printf(“%f %f\n”,c,d); getchar();

return0; }buffer是一个指向用千保存数据的内存位置的指针,size是缓冲区中每个元素的字节数,count是读取或写入的元素数, 当然stream是数据读取或写入的流 buffer参数被解释为一个或多个值的数组。

count参数指定数组中有多少个值,所以读取或写入一个标量时,count的值应为1函数的返回值是实际读取或写入的元素(并非字节)数目如果输入过程中遇到了文件尾或者输出过程中出现了错误, 这个数字可能比请求的元素数目要小。

fread函数用于读取二进制数据,fwrite函数用于写入二进制数据它们的原型如下所示:size_t fread(void *buffer, size_t size, size_t count FILE *stream); 。

size_t fwrite(void *buffer, size_t size, size_t count, FILE *stream);2.2 在数据结构中使用泛型指针void指针在用来实现数据结构时是非常有用的,因为可以通过void指针存储和检索任何类型的数据。

我们再来看一下之前提到过的链表结构ListElmt,回想一下,这个结构包含两个成员:data和next如果data被声明为一个void指针,那么data就可以指向任何类型的数据从而,我们就可以使用ListElmt结构来建立各种不同数据类型的链表。

假设定义了一个链表的操作函数list_ins_next,它的功能是将一个指向data的指针元素插入链表中:typedefstructListElmt_ {void *data;

// 泛型指针structListElmt_ *next; } ListElmt; typedefstructList_ {int size; int (*match)(

constvoid *key1, constvoid *key2); // 函数指针使用泛型指针void (*destroy)(void *data); // 函数指针使用泛型指针

ListElmt *head; ListElmt *tail; } List; int *iptr; intlist_ins_next(List *

list, ListElmt *element, void *data);要将指针iptr引用的整数插入名为list的整型链表中,element引用的元素后面,使用以下调用C语言允许将整型指针iptr赋值给参数data,因为data是一个void指针。

retval = list_ins_next(&list, element, iptr); 当然,当从一个链表中删除数据时,必须使用正确的指针类型来检索要删除的数据这样做是为了保证当我们想要对数据进行操作时数据的类型是正确的。

例如从一个链表中删除元素的函数list_rem_next,它的第三个参数是一个指向void指针的指针:intlist_rem_next(List *list, ListElmt *element, void

**data);  // remove想要从list中element引用的元素后面删除一个整型变量,用如下调用方式当函数返回时,iptr指向已删除的数据这是由于此操作改变了指针本身,使其指向已删除的数据,因此传递iptr指针的地址:。

int *iptr; // 要产生对一级指针的副作用,函数参数要使用一个二级指针 retval = list_rem_next(&list, element, (void **)&iptr);同时,此函数调用包含一个将iptr临时转换为指向void指针的指针的过程。

正如我们之后要讲到的,类型转换是C语言中一种特殊的转换机制,它允许我们临时把一种类型的变量转换为另一种类型的变量在这里,类型转换是必须的,因为C语言中虽然一个void指针与其他类型的指针相兼容,但一个指向void指针的指针并不一定与其他类型的指针兼容。

2.3 泛型指针与类型转换要将类型为T的变量t转换成S类型,只需要在t前加上用圆括号括上的S例如,要将一个整型指针iptr转换为一个浮点型指针fptr,在整型指针前面加上一个用圆括号括起来的浮点指针即可,如下所示:。

fptr = (float *)iptr;(通常来说,将一个整型指针转换为一个浮点型指针是一种危险的做法,但是在这里仅仅用这个例子做一个类型转换的实例而已)在类型转换之后,iptr与fptr都指向同一块内存地址。

但是,从这个地址取到什么类型的值是由我们用什么类型的指针访问它所决定的对于泛型指针来说类型转换非常重要,因为只有告诉泛型指针是通过何种类型来访问地址时,泛型指针才能取到正确的值这是由于泛型指针不会告诉编译器它所指向的是何种类型数据,因此编译器既不知道多少个字节要被访问,也不知道应该如何解析字节。

当将泛型指针赋值给其他类型的指针时,使用类型转换也是一种很好的代码自注释方法尽管这里的转换并不是必需的,但这样做能够大大提高程序的可读性void*类型可以将不同指针类型统一起来进行计算,例如:int a;

char c;&a和&c是不同类型指针,所以&a-&c是非法的,但(void*)&a – (void*)&c是合法的,表示两个变量内存间距下面的函数可以顺利完成这个任务:longmem_distance。

(void *a,void *b){ return a-b; }作为形参的void*可以接收任何类型的指针,实参的指针将会转换为void*类型当转换指针时,我们对内存中的数据对齐方式必须特别注意具体来说,我们需要知道,指针的类型转换会破坏计算机本身的对齐方式。

很多计算机对对齐方式有要求,以便某些硬件的优化可以使访问内存更有效率例如,一个系统可能要求所有整数按字边界对齐所以,如果有一个非按字对齐的void指针,当将它转换为一个整型指针并试图获取它的值时,程序可能在运行时出现异常。

对于void指针,二级void指针可以解引用到一级void指针,一级void指针不能引用,因为你就只有一个地址,没有类型,就不知道需要解引用多少字节?用什么方式解码字节2.4 void*与char*、内存按字节操作。

内存按字节编码,内存操作按字节操作,而char类型的长度是一个字节的长度,所以内存按字节操作可以用char*类型操作来模拟内存操作函数通常以void*为参数,在函数体中转换为char*来操作/* memmove() copies a source memory buffer to a destination memory buffer.This routine recognize overlapping buffers to avoid propogation.For cases where propagation is not a problem, memcpy() can be used. memmove()由src所指定的内存区域赋值count个字符到dst所指定的内存区域。

src和dst所指内 存区域可以重叠,但复制后src的内容会被更改函数返回指向dst的指针 */void * my_memmove(void * dst,constvoid * src,int count)

{ void * ret = dst; if(dst = ((char *)src + count)) { while

(count–) { *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (

char *)src + 1; } } else { dst = (char *)dst + count – 1; src = (

char *)src + count – 1; while(count–) { *(char *)dst = *(char *)src; dst = (

char *)dst – 1; src = (char *)src – 1; } } return(ret); } intmain(){

char a[12]; puts((char *)my_memmove(a,”ammana_babi”,16)); system(“pause”); return0; }3 共用体

一个存储单元可以是枚举的各种数据类型共用一体一个联合的所有成员都存储于同一个内存位置通过访问不同类型的联合成员, 内存中相同的位组合可以被解释为不同的东西联合在实现变体记录时很有用, 但程序员必须负责确认实际存储的是哪个变体并选择正确的联合成员以便访问数据。

联合变量也可以进行初始化, 但初始值必须与联合第1个成员的类型匹配3.1 基本数据类型共用一体一个存储单元可以是枚举的各种基本数据类型共用一体#includetypedefstruct。

Datatype{enum{ character,integer,floating_point }vartype; union{ char c;

int i; double f; }; }datatype; voidprint(datatype *dt){ switch(dt->vartype){ case

character: printf(“character type: %c\n”,dt->c); break; case integer: printf

(“integer type: %d\n”,dt->i); break; case floating_point: printf(“floating_point type: %f\n”

,dt->f); break; } } intmain(){ datatype a; a.vartype = character; a.c = c; print(&a); datatype b; b.vartype = integer; b.i=

2; print(&b); datatype c; c.vartype = floating_point; c.f=3.14; print(&c); getchar();

return0; } /* character type: c integer type: 2 floating_point type: 3.140000 */用C++的类就优雅多了:#include

using namespace std; class datatype{ enum{ character,integer,floating_point }vartype;

union{ char c; int i; double f; }; public: datatype(char ch){ vartype = character; c = ch; } datatype(

int ii){ vartype = integer; i=ii; } datatype(double d){ vartype = floating_point; f=d; }

void print(); }; void datatype::print(){ switch(vartype){ case character: cout<<“character type: “

<

case floating_point: cout<<“floating_point type: “<

c),b(16),c(3.14); a.print(); b.print(); c.print(); getchar(); return0; }3.2 复合数据类型共用一体

一个存储单元可以是枚举的各种复合数据数据类型共用一体在结构体中共用结构体,在Pascal和Modula中被称为变体记录(variant record):#include#include。

#define MAXPARTS 12structParts{// 零件int cost; char supplier[12]; char unit[12] ; }; struct

Assembly{// 装配件int n_parts; struct {char partno[12]; short quan; }parts[MAXPARTS]; }; structInventory

{// 存货类型,或是零件,或是装配件char partno[10]; int quan; enum{PART,ASSEMBLY}type; // 存货类型union { structParts

parts;structAssemblyassembly; }info; }; intmain(){ structInventoryscreen;strcpy(screen.partno,”p001″

); screen.quan = 12; screen.type = Inventory::PART; screen.info.parts.cost = 122; strcpy(screen.info.parts.supplier,

“hw”); strcpy(screen.info.parts.unit,”pcs”); structInventoryshell;strcpy(shell.partno,”a001″); shell.quan =

4; shell.type = Inventory::ASSEMBLY; shell.info.assembly.n_parts=22; strcpy(shell.info.assembly.parts[

0].partno,”d001″); shell.info.assembly.parts[1].quan = 5; int costs; if(shell.type == Inventory::ASSEMBLY) costs = shell.info.assembly.n_parts;

printf(“%d\n”,costs); //22 getchar(); return0; }另一个实例:#include#includestructdate

{int year; int month; int day; }; structmarriedState {structdatemarriedDay;char spouseName[

20]; int child; }; structdivorceState {structdatedivorceDay;int child; }; union maritalState // 婚姻的三种状态

{ int single; structmarriedStatemarried;structdivorceStatedivorce; }; structemployee {char name[

20]; char sex; int age; int marryFlag; union maritalState marital; }; intmain(){

structemployeewwu;strcpy(wwu.name,”wwu”); wwu.sex = M; wwu.age = 18; wwu.marryFlag = 0; wwu.marital.single =

1; printf(“%d\n”,wwu.marital.single); getchar(); return0; }refhttps://www.learncpp.com/cpp-tutorial/void-pointers/

-End-

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
相关推荐
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容