C++ summary C语言实现多态,切割现象

C语言实现多态的简单代码

  • C语言实现多态有点类似回调函数的实现方式
#include <stdio.h>

// 定义回调函数类型
typedef void (*callback_t)(int);

// 实现一个简单的回调函数
void myCallback(int num) {
    printf("Calling back with %d\n", num);
}

// 接受回调函数作为参数的函数
void performActionWithCallback(callback_t cb) {
    printf("Performing an action...\n");
    if (cb) {
        // 调用回调函数
        cb(42); // 假设42是从某个操作中得到的结果
    }
}

int main() {
    // 将回调函数传递给另一个函数
    performActionWithCallback(myCallback);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

// >>>>>接口定义
typedef void (*printer_print_fn)(void *printer,const char *str);

struct printer_i{
		printer_print_fn print;
};
// <<<<<接口定义


// >>>>> plain_printer
struct plain_printer{
	const struct printer_i *interface;
	const char *prefix;
};

    // >>>>> 增强接口定义
    void plain_printer_print(struct plain_printer *self,const char *str);
    void plain_printer_print(struct plain_printer *self,const char *str){
    		printf("%s%s\n",self->prefix,str);
    }
    
    static const struct printer_i printer_interface = {
    		.print = (printer_print_fn)plain_printer_print,
    };
    // <<<<<增强接口定义
    
    struct plain_printer *plain_printer_new(const char *prefix){
    		struct plain_printer *self;
    		self = malloc(sizeof(struct plain_printer));
    		assert(self!=NULL);
    		
    		self->interface = &printer_interface;
    		self->prefix = prefix;
    		return self;
    }
    
    void plain_printer_cleanup(struct plain_printer *self){
    		free(self);
    }
// <<<<< plain_printer

int main()
{
        printf("Hello World");
    	struct plain_printer *p1;
		struct plain_printer *p2;


		struct printer_i **p;// 首先这个 printer 指针,指向的要么是 plain_printer_print,要么是 color_printer_print 。
		                     // 以 plain_printer_print 为例,它的第一个参数是 struct plain_printer *,
		                     // 由于 struct plain_printer 的第一个字段(offset为0的地方)是一个 struct printer_i *,
		                     // 所以 struct plain_printer *(下面的p1和p2) 可以看做一个  struct printer_i **。  同理,struct color_printer * 也可以看做一个  struct printer_i **。
		                     // 用同一个类型把不同结构体统一起来了,这就是这个做法巧妙的地方。
		printf("\n\n");
		p1 = plain_printer_new(">>> ");
		p2 = plain_printer_new("~~~ ");
	
		
		p = (struct printer_i **)p1;
		(*p)->print(p,"hello from p1 ");

		p = (struct printer_i **)p2;
		(*p)->print(p,"hello from p2 ");


		printf("\n\n");
		plain_printer_cleanup(p1);
		plain_printer_cleanup(p2);
    return 0;
}

完整代码

  • 函数指针的正确用法,在理解这个代码之前,最难的部分是把代码敲一遍,敲错了很多字符(๑•̌.•๑)。
#ifndef __PRINTER_H
#define __PRINTER_H
typedef void (*printer_print_fn)(void *printer,const char *str);

struct printer_i{
		printer_print_fn print;
}
#endif
struct plain_printer{
	const struct printer_i *interface;
	const char *prefix;
}

void plain_printer_print(struct plain_printter *self,const char *str);

static const struct printer_i printer_interface = {
		.print = (printer_print_fn)plain_printer_print,
}

struct plain_printer *plain_printer_new(const char *prefix){
		struct plain_printer *self;
		self = malloc(sizeof(struct plain_printer));
		assert(self!=NULL);
		
		self->interface = &printer_interface;
		self->prefix = preifx;
		return self;
}

void plain_printer_cleanup(struct plain_printer *self){
		free(self);
}

void plain_printer_print(struct plain_printer *self,const char *str){
		pritf("%s%s",self->prefix,str);
}
struct color_printer{
	const struct printer_i *interface;
	int enable_color;
	const char *color_command;//*prefix;
	char *buf;
}

void color_printer_print(struct plain_printter *self,const char *str);

static const struct printer_i printer_interface = {
		.print = (printer_print_fn)color_printer_print,
}

struct color_printer *color_printer_new(const char *color_command){
		struct plain_printer *self;
		self = malloc(sizeof(struct plain_printer));
		assert(self!=NULL);
		
		self->interface = &printer_interface;
		self->color_command = color_command == NULL ? "\033[31;40M]" : color_command;
		self->enable_color = 1;
		
		self->buf = malloc(100);
		assert(self->buf ! NULL);
		return self;
}

void color_printer_cleanup(struct plain_printer *self){
		free(self->buf);
		free(self);
}

void color_printer_print(struct color_printer *self,const char *str){
		if(self->enable_color)
			pritf("%s%s\033[0m",self->color_command,str);
		else
			pritf("%s",str);
}
int main(int argc,const char **argv){
		struct plain_printer *p1;
		struct plain_printer *p2;

		struct color_printer *p3;
		struct color_printer *p4;

		struct parinter_i **p;
		printf("\n\n");
		p1 = plain_printer_new(">>> ");
		p2 = plain_printer_new("~~~ ");
		p3 = color_printer_new("\033[31;47m");
		p4 = color_printer_new("\033[30;42m");
		
		p = (struct printer_i **)p1;
		(*p)->print(p,"hello from p1 ");

		p = (struct printer_i **)p2;
		(*p)->print(p,"hello from p2 ");

		p = (struct printer_i **)p3;
		(*p)->print(p,"hello from p3 ");

		p = (struct printer_i **)p4;
		(*p)->print(p,"hello from p4 ");

		color_printer_disable_color(p4);
		(*p)->print(p,"hello from p4 ");

		printf("\n\n");
		plain_printer_cleanup(p1);
		plain_printer_cleanup(p2);
		color_printer_cleanup(p3);
		color_printer_cleanup(p4);

		return 0;		
}

类似切割现象

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

// >>>>>接口定义
typedef void (*printer_print_fn)(void *printer,const char *str);

struct printer_i{
		printer_print_fn print;
};
// <<<<<接口定义


// >>>>> plain_printer
struct plain_printer{
	const struct printer_i *interface;
	const char *prefix;
};

    // >>>>> 增强接口定义
    void plain_printer_print(struct plain_printer *self,const char *str);
    void plain_printer_print(struct plain_printer *self,const char *str){
    		printf("%s%s\n",self->prefix,str);
    }
    
    static const struct printer_i printer_interface = {
    		.print = (printer_print_fn)plain_printer_print,
    };
    // <<<<<增强接口定义
    
    struct plain_printer *plain_printer_new(const char *prefix){
    		struct plain_printer *self;
    		self = malloc(sizeof(struct plain_printer));
    		assert(self!=NULL);
    		
    		self->interface = &printer_interface;
    		self->prefix = prefix;
    		return self;
    }
    
    void plain_printer_cleanup(struct plain_printer *self){
    		free(self);
    }
// <<<<< plain_printer


void printMemory(char *str_discribe,const void *ptr, size_t size) {
    // 将ptr转换为unsigned char类型的指针
    const unsigned char *bytePtr = (const unsigned char *)ptr;
    printf("%s memory of%p,length %zu\n",str_discribe,ptr,size);
    // 输出每个字节的十六进制表示
    for (size_t i = 0; i < size; i++) {
        printf("%02X ", bytePtr[i]);
    }

    printf("\n");
}

int main()
{
        printf("Hello World\n");
    	struct plain_printer *p1;

		struct printer_i **p;// 首先这个 printer 指针,指向的要么是 plain_printer_print,要么是 color_printer_print 。
		                     // 以 plain_printer_print 为例,它的第一个参数是 struct plain_printer *,
		                     // 由于 struct plain_printer 的第一个字段(offset为0的地方)是一个 struct printer_i *,
		                     // 所以 struct plain_printer *(下面的p1和p2) 可以看做一个  struct printer_i **。  同理,struct color_printer * 也可以看做一个  struct printer_i **。
		                     // 用同一个类型把不同结构体统一起来了,这就是这个做法巧妙的地方。
// 		printMemory("P",p,sizeof(*p));
		
		printf("\n\n");
		p1 = plain_printer_new(">>> ");
		printMemory("P1",p1,sizeof(*p1));
	
		
		p = (struct printer_i **)p1;
		(*p)->print(p,"hello from p1 ");
		printMemory("P",p,sizeof(*p));

		
		printf("\n\n");
		plain_printer_cleanup(p1);
    return 0;
}

// P1 memory of0x56362fa266b0,length 16
// 98 2D 2A 2F 36 56 00 00 57 10 2A 2F 36 56 00 00 
// >>> hello from p1 
// P memory of0x56362fa266b0,length 8
// 98 2D 2A 2F 36 56 00 00