luajit中。利用ffi能够嵌入C。眼下luajit的最新版是2.0.4,在这之前的版本号我还不清楚这个扩展库详细怎么样,只是在2.04中,真的非常爽。



既然是嵌入C代码。那么要说让lua支持面向对象。不如说是让C语言模拟面向对象编程。然后让luajit的ffi嵌入。

要文字彻底来描写叙述清楚这个问题。我的表达能力非常有限,说不清楚,所以直接用代码来说吧。

//C++
class foo_type{
public:
void foo1()
{
printf("%d", a + b);
} void foo2(int n)
{
printf("%d", a + b + n);
}
int a;
int b;
}; foo_type obj;
obj.foo1();
obj.foo2(100); //在C语言要做到相同的事。最简单的做法例如以下。 typedef struct{
int a;
int b;
}foo_type;
void foo1(foo_type *obj)
{
printf("%d", obj->a + obj->y);
} void foo2(foo_type *obj, int n)
{
printf("%d", obj->a + obj->y + n);
} foo_type obj;
foo1(&obj);
foo2(&obj, 100); /*****************************************
//C++从汇编语言的角度看
obj.foo1();
lea ecx, obj
call foo1
----------------------- obj.foo2(100);
push 100
lea ecx, obj
call foo1
----------------------- //C语言从汇编语言的角度看
foo1(&obj);
lea eax, obj
push eax
call foo1
----------------------- foo2(&obj, 100);
push 100
lea eax, obj
push eax
call foo2 那么就能够看到,C和C++在实现这样的功能时的差别之处主要在于thiscall使用了ecx寄存器向下传递对象指针
而在C语言。仅仅能把结构指针push下去,这就有点像微软的COM包装类的stdcall的类成员了。 *****************************************/ //从汇编看到问题所在之后,要解决问题,也就在能够考虑写一个shellcode,这个shellcode实现将向下传递上层传入的參数。而且直接将结构指针以push參数的方式最后入栈。然后call就可以。
typedef struct{
int a;
int b;
}foo_type;
void foo1(foo_type *obj)
{
printf("%d", obj->a + obj->y);
} void foo2(foo_type *obj, int n)
{
printf("%d", obj->a + obj->y + n);
} typedef struct{
void (*foo1)();
void (*foo2)(int n);
}foo_class; foo_type ft;
foo_class obj;
//与foo1相应的shellcode模板
BYTE scT1[] = {
0x68, 0, 0, 0, 0, //push CONST
0xE8, 0, 0, 0, 0, //call CONST
0x83, 0xC4, 0x04, //add esp, 4
0xC3 //ret
}; BYTE *psc = (BYTE*)VirtualAlloc(NULL, sizeof(scT1), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(psc, scT1, sizeof(scT1));
*(ULONG*)(psc + 1) = (ULONG)&ft;
*(ULONG*)(psc + 6) = (ULONG)&foo1 - (ULONG)(psc + 5) - 5;
*(ULONG*)&(obj.foo1) = psc; //到这里之后,就已经能够这样用了
obj.foo1(); //与foo2相应的shellcode模板
BYTE scT2[] = {
0xFF, 0x74, 0x24, 0x04, //push dword ptr [esp + 4]
0x68, 0, 0, 0, 0, //call CONST
0xE8, 0, 0, 0, 0, //call CONST
0x83, 0xC4, 0x08, //add esp, 8
0xC3 //ret
};
BYTE *psc = (BYTE*)VirtualAlloc(NULL, sizeof(scT2), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(psc, scT2, sizeof(scT2));
*(ULONG*)(psc + 5) = (ULONG)&ft;
*(ULONG*)(psc + 10) = (ULONG)&foo2 - (ULONG)(psc + 5) - 5;
*(ULONG*)&(obj.foo2) = psc; obj.foo2(100); //这样就模拟了面向对象形式的调用,之后就须要考虑的就是一些怎样整合管理资源之类的问题,还须要将代码尽可能的利用一些宏来简化,这些东西就不在这里说了,这个思路深入下去。相信大家都会知道该怎么做了。

以下是一套我封装的luajit使用ODBC訪问数据库的代码,没有凝视。将就着看吧。

//luaodbc.h**************************************************
#pragma once extern "C"{
typedef struct{
void (*close)();
bool (*set)(int i, int type, char *data, int size);
bool (*get)(int i, int type);
void *(*data)();
bool (*next)();
char *(*getstr)(int i);
int (*getint)(int i);
char *(*getstr_fn)(const char *name);
char *(*getint_fn)(const char *name);
bool (*setstr)(int i, const char *str);
bool (*setint)(int i, int num);
bool (*setstr_fn)(const char *name, const char *str);
bool (*setint_fn)(const char *name, int num);
}luastmt_class; typedef struct{
bool (*open)(const char*dsn);
void (*close)();
luastmt_class *(*exec)(const char *sql);
void (*tran_begin)();
void (*tran_end)(int ct);
}luadbc_class; __declspec(dllexport) luadbc_class *luadbc_init();
__declspec(dllexport) void luadbc_exit(luadbc_class *obj);
}; //luaodbc.cpp**************************************************
#include "stdafx.h"
#include "luaodbc.h"
#include <sql.h>
#include <sqlext.h>
#include <list>
#include <algorithm>
#include <string> extern "C"{
#define LOS_CLOSED 0
#define LOS_INITILZED 1
#define LOS_CONNECTIONED 2
#define LOS_TRAN 4
#define LOS_STMTOPENED 8 typedef struct _ciType{
char name[68];
int type;
int type_len;
char *data;
int data_size;
int nds;
}ciType; typedef struct _stmtType{
SQLHANDLE hstmt;
ciType *cols;
int col_count;
int cp_size;
unsigned int status;
void *parent;
luastmt_class thisobj;
unsigned char *class_memory;
int gci;
_stmtType *next;
}stmtType; typedef struct{
int (*open)(const char*dsn);
void (*close)();
bool (*exec)(const char *sql);
void (*tran_begin)();
void (*tran_end)(int ct);
void *dbc_obj;
}luadbc_class_ex; typedef struct _odbcType{
SQLHANDLE henv, hdbc;
_stmtType *stmt_list;
unsigned int status;
luadbc_class_ex thisobj;
unsigned char *class_memory;
}odbcType; BYTE scT1[] = {
0x68, 0, 0, 0, 0,
0xE8, 0, 0, 0, 0,
0x83, 0xC4, 0x04,
0xC3
}; BYTE scT2[] = {
0xFF, 0x74, 0x24, 0x04,
0x68, 0, 0, 0, 0,
0xE8, 0, 0, 0, 0,
0x83, 0xC4, 0x08,
0xC3
}; BYTE scT3[] = {
0xFF, 0x74, 0x24, 0x08,
0xFF, 0x74, 0x24, 0x08,
0x68, 0, 0, 0, 0,
0xE8, 0, 0, 0, 0,
0x83, 0xC4, 0x0C,
0xC3
}; BYTE scT4[] = {
0xFF, 0x74, 0x24, 0x0C,
0xFF, 0x74, 0x24, 0x0C,
0xFF, 0x74, 0x24, 0x0C,
0x68, 0, 0, 0, 0,
0xE8, 0, 0, 0, 0,
0x83, 0xC4, 0x10,
0xC3
}; BYTE scT5[] = {
0xFF, 0x74, 0x24, 0x10,
0xFF, 0x74, 0x24, 0x10,
0xFF, 0x74, 0x24, 0x10,
0xFF, 0x74, 0x24, 0x10,
0x68, 0, 0, 0, 0,
0xE8, 0, 0, 0, 0,
0x83, 0xC4, 0x14,
0xC3
}; #define SCTP1 1
#define SCTP2 SCTP1 + 4
#define SCTP3 SCTP2 + 4
#define SCTP4 SCTP3 + 4
#define SCTP5 SCTP4 + 4 std::list<int> g_safe_luaodbc_list;
CRITICAL_SECTION g_safe_luaodbc_cs;
class luaodbc_startup{
public:
luaodbc_startup()
{
InitializeCriticalSection(&g_safe_luaodbc_cs);
static_link = 1;
}
int static_link;
}; static luaodbc_startup g_luaodbc_link;
static int ___g_static_link = g_luaodbc_link.static_link; void luastmt_close(stmtType *v)
{
if(v->status & LOS_STMTOPENED)
{
SQLFreeHandle(SQL_HANDLE_STMT, v->hstmt);
v->hstmt = NULL;
v->status ^= LOS_STMTOPENED;
}
} void luaodbc_coldata_realloc(stmtType *v, int i, int size)
{
delete v->cols[i].data;
v->cols[i].data = new char[size];
} BOOL luastmt_set(stmtType *v, int i, int type, char *data, int size)
{
if(!data || i <= 0)
return FALSE;
if(!(v->status & LOS_STMTOPENED))
return FALSE;
SQLINTEGER ncb = size;
//printf("data:%s, i:%d, len:%d, type:%d\n", data,i, size, type);
SQLFreeStmt(v->hstmt, SQL_UNBIND);
SQLRETURN rc = SQLBindCol(v->hstmt, (SQLUSMALLINT)i, (SQLSMALLINT)type, (SQLPOINTER)data, (SQLINTEGER)size, &ncb);
if(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
SQLSetPos(v->hstmt, 1, SQL_UPDATE, SQL_LOCK_NO_CHANGE);
//printf("update:%d, %d\n", rc, ncb);
SQLFreeStmt(v->hstmt, SQL_UNBIND);
return TRUE;
} BOOL luastmt_get(stmtType *v, int i, int type)
{
if(i <= 0)
return FALSE;
if(!(v->status & LOS_STMTOPENED))
return FALSE;
SQLRETURN rc;
for(;;)
{
if(v->gci == i)
SQLSetPos(v->hstmt, 1, SQL_POSITION, SQL_LOCK_NO_CHANGE);
else
v->gci = i;
rc = SQLGetData(v->hstmt, i, type,
v->cols[i - 1].data, v->cols[i - 1].data_size, (SQLINTEGER*)&(v->cols[i - 1].nds));
if(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
return TRUE;
if(v->cols[i - 1].data_size < v->cols[i - 1].nds)
luaodbc_coldata_realloc(v, i - 1, v->cols[i - 1].nds + 1);
else
return FALSE;
}
return false;
} void *luastmt_dataptr(stmtType *v, int i)
{
if(i <= 0)
return false;
return v->cols[i - 1].data;
} BOOL luastmt_next(stmtType *v)
{
if(!(v->status & LOS_STMTOPENED))
return false;
v->gci = 0;
SQLRETURN rc = SQLFetch(v->hstmt);
return (rc != SQL_NO_DATA_FOUND);
} const char *luastmt_getstr(stmtType *v, int i)
{
if(!luastmt_get(v, i, SQL_C_CHAR))
return "";
return v->cols[i - 1].data;
} int luastmt_getint(stmtType *v, int i)
{
if(!luastmt_get(v, i, SQL_C_SLONG))
return -1;
return *(int*)(v->cols[i - 1].data);
} int _colindexfromename(stmtType *v, const char *name)
{
std::string str = name;
std::transform(str.begin(), str.end(), str.begin(), tolower);
for(short i = 0; i < v->col_count; i++)
{
if(str == (v->cols)[i].name)
return i + 1;
}
return -1;
} const char *luastmt_getstr_fn(stmtType *v, const char *name)
{
if(!name)
return "";
return luastmt_getstr(v, _colindexfromename(v, name));
} int luastmt_getint_fn(stmtType *v, const char *name)
{
if(!name)
return -1;
return luastmt_getint(v, _colindexfromename(v, name));
} BOOL luastmt_setstr(stmtType *v, int i, const char *str)
{
if(i <= 0 || !str)
return FALSE;
return luastmt_set(v, i, SQL_C_CHAR, (char*)str, strlen(str) + 1);
} BOOL luastmt_setint(stmtType *v, int i, int num)
{
if(!v || i <= 0)
return FALSE;
return luastmt_set(v, i, SQL_C_SLONG, (char*)&num, sizeof(int));
} BOOL luastmt_setstr_fn(stmtType *v, const char *name, const char *str)
{
if(!v || !name)
return false;
return luastmt_setstr(v, _colindexfromename(v, name), str);
} BOOL luastmt_setint_fn(stmtType *v, const char *name, int num)
{
if(!name)
return false;
return luastmt_setint(v, _colindexfromename(v, name), num);
} void luastmt_class_init(stmtType *v)
{
BYTE *psc = v->class_memory;
#define make_luastmt_shellcode(_member_, _sc_t_, _pup_, _proc_) *(DWORD*)&(v->thisobj._member_) = (DWORD)psc; \
memcpy_s(psc, sizeof(_sc_t_), _sc_t_, sizeof(_sc_t_)); \
*(DWORD*)(psc + _pup_) = (DWORD)v; \
*(DWORD*)(psc + _pup_ + 5) = (DWORD)_proc_ - (DWORD)(psc + _pup_ + 5 - 1) - 5; \
psc += sizeof(_sc_t_)
make_luastmt_shellcode(close, scT1, SCTP1, luastmt_close);
make_luastmt_shellcode(set, scT5, SCTP5, luastmt_set);
make_luastmt_shellcode(get, scT3, SCTP3, luastmt_get);
make_luastmt_shellcode(data, scT1, SCTP1, luastmt_dataptr);
make_luastmt_shellcode(next, scT1, SCTP1, luastmt_next);
make_luastmt_shellcode(getstr, scT2, SCTP2, luastmt_getstr);
make_luastmt_shellcode(getint, scT2, SCTP2, luastmt_getint);
make_luastmt_shellcode(getstr_fn, scT2, SCTP2, luastmt_getstr_fn);
make_luastmt_shellcode(getint_fn, scT2, SCTP2, luastmt_getint_fn);
make_luastmt_shellcode(setstr, scT3, SCTP3, luastmt_setstr);
make_luastmt_shellcode(setint, scT3, SCTP3, luastmt_setint);
make_luastmt_shellcode(setstr_fn, scT3, SCTP3, luastmt_setstr_fn);
make_luastmt_shellcode(setint_fn, scT3, SCTP3, luastmt_setint_fn);
} void luastmt_colinfo_release(stmtType *v)
{
for(int i = 0; i < v->cp_size; i++)
{
if(v->cols[i].data)
{
delete v->cols[i].data;
v->cols[i].data = NULL;
}
}
delete v->cols;
} void luastmt_colinfo_init(stmtType *v)
{
short count;
SQLNumResultCols(v->hstmt, &count);
if(count > v->cp_size)
{
luastmt_colinfo_release(v);
v->cp_size = count;
v->cols = new ciType[count];
memset(v->cols, 0, sizeof(ciType) * count);
}
v->col_count = count;
char szColName[68];
SQLSMALLINT cbColName, sqlColType, ibScale, fNullable;
SQLUINTEGER cbColDef;
for(short i = 0; i < count; i++)
{
SQLDescribeColA(v->hstmt, i + 1, (SQLCHAR*)szColName, 68, &cbColName, &sqlColType, &cbColDef, &ibScale, &fNullable);
for(short j = 0; j < cbColName; j++)szColName[j] = tolower(szColName[j]);
memcpy_s(v->cols[i].name, 68, szColName, cbColName + 1);
if(v->cols[i].data_size < (int)cbColDef + 1)
{
if(v->cols[i].data)
delete v->cols[i].data;
v->cols[i].data_size = cbColDef + 1;
v->cols[i].data = new char[cbColDef + 1];
}
v->cols[i].type = sqlColType;
v->cols[i].type_len = cbColDef;
}
} void luastmt_release(stmtType *v)
{
luastmt_colinfo_release(v);
VirtualFree(v->class_memory, 0, MEM_RELEASE);
delete v;
} stmtType *luaodbc_newstmt(_odbcType *parent)
{
stmtType *v = new stmtType;
memset(v, 0, sizeof(stmtType));
v->cp_size = 64;
v->cols = new ciType[64];
memset(v->cols, 0, sizeof(ciType) * 64);
v->status = LOS_CLOSED;
v->next = NULL;
v->parent = parent;
v->class_memory = (unsigned char *)VirtualAlloc(NULL, 512, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
luastmt_class_init(v);
return v;
} void luaodbc_tran_begin(odbcType *v)
{
SQLSetConnectAttrA(v->hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_FALSE, NULL);
v->status |= LOS_TRAN;
} void luaodbc_tran_end(odbcType *v, int ct)
{
SQLEndTran(SQL_HANDLE_DBC, v->hdbc, (short)ct);
SQLSetConnectAttrA(v->hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_TRUE, NULL);
v->status ^= LOS_TRAN;
} void luaodbc_close(odbcType *v)
{
if(v->status & LOS_CONNECTIONED)
{
stmtType *s = v->stmt_list;
do{
luastmt_close(s);
s = s->next;
}while(s);
if(v->status & LOS_TRAN)
luaodbc_tran_end(v, SQL_ROLLBACK);
SQLDisconnect(v->hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, v->hdbc);
v->status ^= LOS_CONNECTIONED;
v->hdbc = NULL;
}
} BOOL luaodbc_open(odbcType *v, const char *dsn)
{
luaodbc_close(v);
SQLHANDLE hdbc;
SQLRETURN rc = SQLAllocHandle(SQL_HANDLE_DBC, v->henv, &hdbc);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
return FALSE;
rc = SQLConnectA(hdbc, (SQLCHAR*)dsn, SQL_NTS, NULL, 0, NULL, 0);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
return FALSE;
}
v->hdbc = hdbc;
v->status |= LOS_CONNECTIONED;
return TRUE;
} luastmt_class *luaodbc_exec(odbcType *v, const char *sql)
{
stmtType *s = v->stmt_list;
stmtType *b = s;
do{
if(!(s->status & LOS_STMTOPENED))
break;
b = s;
s = s->next;
}while(s); if(!s)
{
s = luaodbc_newstmt(v);
b->next = s;
} SQLHANDLE hstmt;
SQLRETURN rc;
if(!(v->status & LOS_CONNECTIONED))
return NULL; rc = SQLAllocHandle(SQL_HANDLE_STMT, v->hdbc, &hstmt);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
return FALSE;
SQLCancel(hstmt);
#if(_MSC_VER < 1300)
SQLSetStmtOption(hStmt, SQL_CONCURRENCY, SQL_CONCUR_VALUES);
SQLSetStmtOption(hStmt, SQL_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);
#else
SQLSetStmtAttr(hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER)SQL_CONCUR_VALUES, 0);
SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);
#endif
rc = SQLExecDirectA(hstmt, (SQLCHAR*)sql, SQL_NTS);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
//printf("ERROR:[ODBC::Connection::Execute]->%s\n", sql);
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
return FALSE;
}
s->hstmt = hstmt;
luastmt_colinfo_init(s);
s->status |= LOS_STMTOPENED;
return &(s->thisobj);
} void luaodbc_class_init(odbcType *v)
{
BYTE *psc = v->class_memory;
#define make_luaodbc_shellcode(_member_, _sc_t_, _pup_, _proc_) *(DWORD*)&(v->thisobj._member_) = (DWORD)psc; \
memcpy_s(psc, sizeof(_sc_t_), _sc_t_, sizeof(_sc_t_)); \
*(DWORD*)(psc + _pup_) = (DWORD)v; \
*(DWORD*)(psc + _pup_ + 5) = (DWORD)_proc_ - (DWORD)(psc + _pup_ + 5 - 1) - 5; \
psc += sizeof(_sc_t_)
make_luaodbc_shellcode(open, scT2, SCTP2, luaodbc_open);
make_luaodbc_shellcode(close, scT1, SCTP1, luaodbc_close);
make_luaodbc_shellcode(exec, scT2, SCTP2, luaodbc_exec);
make_luaodbc_shellcode(tran_begin, scT1, SCTP1, luaodbc_tran_begin);
make_luaodbc_shellcode(tran_end, scT2, SCTP2, luaodbc_tran_end);
} __declspec(dllexport) luadbc_class *luadbc_init()
{
odbcType *v = new odbcType;
memset(v, 0, sizeof(odbcType));
SQLRETURN rc;
rc = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &(v->henv));
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
return NULL;
rc = SQLSetEnvAttr(v->henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
SQLFreeHandle(SQL_HANDLE_ENV, v->henv);
v->henv = NULL;
return NULL;
}
v->stmt_list = luaodbc_newstmt(v);
v->status = LOS_INITILZED;
v->class_memory = (unsigned char *)VirtualAlloc(NULL, 512, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
luaodbc_class_init(v);
v->thisobj.dbc_obj = v;
EnterCriticalSection(&g_safe_luaodbc_cs);
g_safe_luaodbc_list.push_back((int)&(v->thisobj));
LeaveCriticalSection(&g_safe_luaodbc_cs);
return (luadbc_class*)&(v->thisobj);
} __declspec(dllexport) void luadbc_exit(luadbc_class *obj)
{
EnterCriticalSection(&g_safe_luaodbc_cs);
auto it = std::find(g_safe_luaodbc_list.begin(), g_safe_luaodbc_list.end(), (int)obj);
if(it == g_safe_luaodbc_list.end())
{
LeaveCriticalSection(&g_safe_luaodbc_cs);
return;
}
g_safe_luaodbc_list.erase(it);
LeaveCriticalSection(&g_safe_luaodbc_cs);
odbcType *v = (odbcType*)(((luadbc_class_ex*)obj)->dbc_obj);
VirtualFree(v->class_memory, 0, MEM_RELEASE);
luaodbc_close(v);
stmtType *s = v->stmt_list;
stmtType *b;
do{
b = s;
s = s->next;
luastmt_release(b);
}while(s);
SQLFreeHandle(SQL_HANDLE_ENV, v->henv);
delete v;
}
}
--luajit中这样调用
local ffi = require("ffi")
ffi.cdef[[
typedef struct{
void (*close)();
bool (*set)(int i, int type, char *data, int size);
bool (*get)(int i, int type);
void *(*data)();
bool (*next)();
char *(*getstr)(int i);
int (*getint)(int i);
char *(*getstr_fn)(const char *name);
char *(*getint_fn)(const char *name);
bool (*setstr)(int i, const char *str);
bool (*setint)(int i, int num);
bool (*setstr_fn)(const char *name, const char *str);
bool (*setint_fn)(const char *name, int num);
}luastmt_class; typedef struct{
bool (*open)(const char*dsn);
void (*close)();
luastmt_class *(*exec)(const char *sql);
void (*tran_begin)();
void (*tran_end)(int ct);
}luadbc_class; luadbc_class *luadbc_init();
void luadbc_exit(luadbc_class *obj);
]] local conn = ffi.C.luadbc_init(); if conn.open("USERDSN") ~= false then
print("已连接!")
local rs = conn.exec("SELECT * FROM characters")
if rs ~= nil then
print("開始遍历数据!")
while rs.next() do
print(ffi.string(rs.getstr(3)))
end
rs.close()
end
conn.close()
end

luajit利用ffi结合C语言实现面向对象的封装库的更多相关文章

  1. 用C语言实现面向对象的开发

    C语言的对象化模型 面向对象的特征主要包括: .封装,隐藏内部实现 .继承,复用现有代码 .多态,改写对象行为 采用C语言实现的关键是如何运用C语言本身的特性来实现上述面向对象的特征. 1.1 封装 ...

  2. 基于C语言的面向对象编程

    嵌入式软件开发中,虽然很多的开发工具已经支持C++的开发,但是因为有时考虑运行效率和编程习惯,还是有很多人喜欢用C来开发嵌入式软件.Miro Samek说:"我在开发现场发现,很多嵌入式软件 ...

  3. 已看1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架、多线程(并发编程)、I/O(NIO)、Socket、JDBC、XML、反射等。[泛型]\

    1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架.多线程(并发编程).I/O(NIO).Socket.JDBC.XML.反射等.[泛型]\1* ...

  4. LuaJIT 之 FFI

    1. FFI 教程 原文: FFI Tutorial 相关链接:OpenResty 最佳实践之 FFI 加载 FFI 库 FFI 库时默认编译进 LuaJIT 中的,但是不会默认加载或初始化.因此,当 ...

  5. 使C语言实现面向对象的三个要素,你掌握了吗?

  6. Python语言之面向对象

    Python语言之面向对象 前言 面向对象 -- Object Oriented 简写:OO 面向对象设计 -- Object Oriented Design 简写:OOD 面向对象编程 -- Obj ...

  7. Objective-C语言的面向对象特性

    Objective-C作为一种面向对象的编程语言,具有面向对象的基本特征,即:封装.继承和多态.主要介绍Objective-C中有关面向对象基本概念:类.对象.方法和属性等. 类是Objective- ...

  8. [java学习笔记]java语言核心----面向对象之this关键字

    一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别:在构造函数中调用其它构造函数 原理:         代表的是当前对象.         this就是所在函数 ...

  9. 第二十五节:Java语言基础-面向对象基础

    面向对象 面向过程的代表主要是C语言,面向对象是相对面向过程而言,Java是面向对象的编程语言,面向过程是通过函数体现,面向过程主要是功能行为. 而对于面向对象而言,将功能封装到对象,所以面向对象是基 ...

随机推荐

  1. jQuery 首页搜索区域模块随页面滑动而变化

    /*搜索区块的颜色变化*/ function search(){ var searchBox = document.querySelector('.m_head'); var bannerBox = ...

  2. Java 类执行顺序

    1.如果父类有静态成员赋值或者静态初始化块,执行静态成员赋值和静态初始化块2.如果类有静态成员赋值或者静态初始化块,执行静态成员赋值和静态初始化块3.将类的成员赋予初值(原始类型的成员的值为规定值,例 ...

  3. filezilla server FTP 安装报错 "could not load TLS network. Aborting start of administration interface"

    filezilla server FTP 安装报错   "could not load TLS network. Aborting start of administration inter ...

  4. pycharm debug后会出现 step over /step into/step into my code /force step into /step out 分别表示

    1.debug,全部打印 2.打断点debug,出现单步调试等按钮,只运行断点前 3.setup over 调试一行代码 4.setup out 运行断点后面所有代码 5.debug窗口显示调试按钮 ...

  5. Git的入门

    Git的基本介绍: Git:是一个版本控制工具. Github:是非常有名的在线版本管理网站(速度比较慢). Oschina:中国版本的github,(旗下的的码云地址:gitee.com,速度快) ...

  6. Mybatis的一级二级缓存

    Mybatis提供了缓存机制,可以减轻数据库的压力,提高性能 Mybatis的缓存分为两级:一个是一级缓存,一个二级缓存 一级缓存:即默认使用的缓存SqlSession级别的缓存,只在sqlsessi ...

  7. 微信小程序 设置计时器(setInterval)、清除计时器(clearInterval)

    1.wxml代码 <!--index.wxml--> <view class="container"> <button type='primary' ...

  8. Mysql:零散记录

    limit用法 查询第4行记录 select * from tablename limit 3,1; limit 3,1:截取第3行加1行的数据 查询第6-15行 select * from tabl ...

  9. 集训第四周(高效算法设计)E题 (区间覆盖问题)

    UVA10382 :http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21419 只能说这道题和D题是一模一样的,不过要进行转化, ...

  10. HDU 1564 找规律博弈

    题目大意是: 从n*n的方格角落的一个起点出发,每次移到上下左右一个未曾到达过的位置,谁不能走了谁就输了 想了好久都想不出,看了大神的题解 Orz了 果然博弈不是脑残的游戏啊... 这里从起点出发,将 ...