1. 程式人生 > >類屬回撥的實驗

類屬回撥的實驗

前言

以前也總結過2次使用類屬回撥函式的方法。總是要借用靜態函式,很醜。
上個週末在做其他實驗時,也用到了類屬回撥.
這次找的資料中,使用類屬回撥的方式很優雅。

demo下載點

src_test_class_callback.7z

工程預覽

// @file main.cpp
// @brief 對mysql操作進行封裝, 使操作mysql資料庫方便些
// @note 
//		實驗環境:
//				debian8.8

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <errno.h>

#include "const_define.h"

void init(const char* psz_log_owner_name);
void uninit();
void proc_sig_term(int num);
int fn_test(int argc, char** argv);

class cls_test_callback
{
public:
	typedef bool (cls_test_callback::*PFN_cb_proc_2_number)(
		int i, int j, bool& b_process_ok);

public:
	cls_test_callback()
	{
		m_i = 0;
		m_j = 0;
	}
	
	~cls_test_callback() {}

	void set_data(int i, int j)
	{
		m_i = i;
		m_j = j;
	}

	bool process_2_number(PFN_cb_proc_2_number cb)
	{
		bool b_rc = false;

		do {
			if (NULL == cb) {
				break;
			}

			if (!(this->*cb)(m_i, m_j, b_rc)) {
				// call back proc say : need not to call back next
				break;
			}
		} while (0);

		return b_rc;
	}

	bool math_add(int i, int j, bool& b_process_ok)
	{
		MYLOG_D("%d + %d = %d\n", i, j, i + j);
		b_process_ok = true;
		return false;
	}

	bool math_sub(int i, int j, bool& b_process_ok)
	{
		MYLOG_D("%d - %d = %d\n", i, j, i - j);
		b_process_ok = true;
		return false;
	}

private:
	int m_i;
	int m_j;
};

int fn_test(int argc, char** argv)
{
	bool b_rc = false;
    MYLOG_D(">> fn_test()\n");
	
	cls_test_callback test_cb;

	do {
		test_cb.set_data(100, 200);
		test_cb.process_2_number(&cls_test_callback::math_add);
		test_cb.process_2_number(&cls_test_callback::math_sub);

		/** run result
		Oct 29 16:05:22 localhost test_class_callback: [MYLOG_D : main.cpp.110 : main()] : MAKE_FILE_MACRO__BIN_NAME = [test_class_callback]
		Oct 29 16:05:22 localhost test_class_callback: [MYLOG_D : main.cpp.84 : fn_test()] : >> fn_test()
		Oct 29 16:05:22 localhost test_class_callback: [MYLOG_D : main.cpp.64 : math_add()] : 100 + 200 = 300
		Oct 29 16:05:22 localhost test_class_callback: [MYLOG_D : main.cpp.71 : math_sub()] : 100 - 200 = -100
		Oct 29 16:05:22 localhost test_class_callback: [MYLOG_D : main.cpp.118 : main()] : THE END
		*/
	
		b_rc = true;
	} while (0);

	if (!b_rc) {
		MYLOG_D("test failed r\n");
	}

    return 0;
}

int main(int argc, char** argv)
{
    char sz_buf[MAX_MSG_LENGTH] = {'\0'};

#ifdef MAKE_FILE_MACRO__BIN_NAME
    sprintf(sz_buf, "%s", MAKE_FILE_MACRO__BIN_NAME);
    init(sz_buf);
    MYLOG_D("MAKE_FILE_MACRO__BIN_NAME = [%s]\n", MAKE_FILE_MACRO__BIN_NAME);
#else
    init(NULL);
#endif // #ifdef MAKE_FILE_MACRO__BIN_NAME

    fn_test(argc, argv);
    uninit();

    MYLOG_D("THE END\n");
    return EXIT_SUCCESS;
}

void uninit()
{
}

void proc_sig_term(int num)
{
    MYLOG_D("SIGTERM = %d, num = %d\n", SIGTERM, num);
    MYLOG_D("maybe can do some clean task before quit\n");
    exit(1);	
}

void init(const char* psz_log_owner_name)
{
    int i = 0;

    // daemon(0, 0);

    // clear screen (print 25 empty line)
    for (i = 0; i < 25; i++) {
        MYLOG_D("\n");
    }

    signal(SIGTERM, proc_sig_term);
}


// @file const_define.h

#if not defined(__CONST_DEFINE_H__)
#define __CONST_DEFINE_H__

#include <string.h>
#include <stdint.h>
#include <syslog.h>

#include <string>
#include <list>

typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned long long ull;

#ifndef SAFE_DELETE
#define SAFE_DELETE(p) \
    if (NULL != (p)) { \
        delete (p); \
        (p) = NULL; \
    }
#endif // #ifndef SAFE_DELETE

#ifndef SAFE_DELETE_ARY
#define SAFE_DELETE_ARY(p) \
    if (NULL != (p)) { \
        delete[] (p); \
        (p) = NULL; \
    }
#endif // #ifndef SAFE_DELETE

#define TITLE_LINE80 "================================================================================"
#define LINE80 "--------------------------------------------------------------------------------"

#if not defined(MYLOG_D)

#define USE_SYSLOG

#ifdef USE_SYSLOG
#define MYLOG_V(fmt, ...) \
	syslog(LOG_INFO, "[%s : %s.%d : %s()] : " fmt, "MYLOG_V", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);

#define MYLOG_D(fmt, ...) \
	syslog(LOG_INFO, "[%s : %s.%d : %s()] : " fmt, "MYLOG_D", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);

#define MYLOG_I(fmt, ...) \
	syslog(LOG_INFO, "[%s : %s.%d : %s()] : " fmt, "MYLOG_I", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);

#define MYLOG_W(fmt, ...) \
	syslog(LOG_INFO, "[%s : %s.%d : %s()] : " fmt, "MYLOG_W", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);

#define MYLOG_E(fmt, ...) \
	syslog(LOG_INFO, "[%s : %s.%d : %s()] : " fmt, "MYLOG_E", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);

#define MYLOG_F(fmt, ...) \
	syslog(LOG_INFO, "[%s : %s.%d : %s()] : " fmt, "MYLOG_F", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);
#else // #ifdef USE_SYSLOG
#define MYLOG_V printf
#define MYLOG_D printf
#define MYLOG_I printf
#define MYLOG_W printf
#define MYLOG_E printf
#define MYLOG_F printf
#endif // #ifdef USE_SYSLOG

#endif // #if not defined(MYLOG_D)

#define MAX_MSG_LENGTH (1024 * 4)

#endif // #if not defined(__CONST_DEFINE_H__)


# ==============================================================================
# @file makefile
# ==============================================================================
# @note 
# howto build project
# 		make BIN_NAME="bin_name_by_you_want" rebuild
# makefile code need tab key not sapce key

MY_MAKE_FILE_PATH_NAME = $(MAKEFILE_LIST)

# macro from Makefile command line
# BIN_NAME

# macro to C project
MAKE_FILE_MACRO__BIN_NAME="make_file_macro__bin_name"

# var define on Makefile
BIN = output_not_give_bin_name
IS_BUILD_TYPE_VALID = 0

ifdef BIN_NAME
	IS_BUILD_TYPE_VALID = 1
	BIN = $(BIN_NAME)
	MAKE_FILE_MACRO__BIN_NAME=$(BIN_NAME)
else
	IS_BUILD_TYPE_VALID = 0
endif

LINE80 = --------------------------------------------------------------------------------

# CC = g++ -std=c++98
CC = g++

# -Werror is "warning as error"
CFLAGS = -Wall -Werror -g

INC = -I.
LIBPATH = -L. -L/usr/lib/ -L/usr/local/lib/

ifeq (1, $(IS_BUILD_TYPE_VALID))
	LIBS = -lstdc++ -pthread
else
	LIBS =
endif

DEPEND_CODE_DIR = ../common/ \

DEPEND_CODE_SRC = $(shell find $(DEPEND_CODE_DIR) -name '*.cpp')
DEPEND_CODE_OBJ = $(DEPEND_CODE_SRC:.cpp=.o)

ROOT_CODE_SRC = $(shell find ./ -name '*.cpp')
ROOT_CODE_OBJ = $(ROOT_CODE_SRC:.cpp=.o)

SUB_CODE_DIR = ./empty_dir
SUB_CODE_SRC = $(shell find $(SUB_CODE_DIR) -name '*.cpp')
SUB_CODE_OBJ = $(SUB_CODE_SRC:.cpp=.o)

.PHONY: help
help:
	clear
	@echo "usage:"
	@echo
	@echo "build project by given bin name"
	@echo "make BIN_NAME=\"bin_name_by_you_want\" rebuild"
	@echo

.PHONY: clean
clean:
	clear

	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo

	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo

	@echo
	@echo
	@echo
	@echo
	@echo

	@echo "make clean begin"
	@echo $(LINE80)

	@echo "@file $(MY_MAKE_FILE_PATH_NAME)"
	@echo "IS_BUILD_TYPE_VALID = $(IS_BUILD_TYPE_VALID)"
	@echo "BIN = $(BIN)"

	@echo $(LINE80)

	rm -f $(ROOT_CODE_OBJ) $(DEPEND_CODE_OBJ) $(SUB_CODE_OBJ)

ifeq (1, $(IS_BUILD_TYPE_VALID))
	rm -f ./$(BIN)
endif

	@echo "make clean over"

.PHONY: all
all:$(BIN)
	@echo $(LINE80)
	@echo make all
	chmod 777 ./$(BIN)
	find . -name "$(BIN)"

$(BIN) : $(ROOT_CODE_OBJ) $(DEPEND_CODE_OBJ) $(SUB_CODE_OBJ)
	$(CC) $(CFLAGS) -o 
[email protected]
$^ $(SHLIBS) $(INC) $(LIBPATH) $(LIBS) .cpp.o: $(CC) -c $(CFLAGS) -DMAKE_FILE_MACRO__BIN_NAME="\"$(MAKE_FILE_MACRO__BIN_NAME)\"" $^ -o [email protected] $(INC) $(LIBPATH) $(LIBS) .PHONY: rebuild rebuild: make -f $(MY_MAKE_FILE_PATH_NAME) clean ifeq (1, $(IS_BUILD_TYPE_VALID)) @echo $(LINE80) make -f $(MY_MAKE_FILE_PATH_NAME) all chmod 775 ./$(BIN) ldd ./$(BIN) else @echo $(LINE80) @echo "error : Makefile command line input error, please see help" @echo "please run => make help" @echo $(LINE80) endif
#!/bin/bash
# ==============================================================================
# @file build_all_project.sh
# ==============================================================================

make BIN_NAME="test_class_callback" rebuild