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 ) ;
}
}
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;
} ;
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) ;
}
int main ( )
{
printf ( "Hello World" ) ;
struct plain_printer * p1;
struct plain_printer * p2;
struct printer_i * * p;
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;
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