国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

網(wǎng)站建設(shè)的最新技術(shù)寧波seo優(yōu)化公司

網(wǎng)站建設(shè)的最新技術(shù),寧波seo優(yōu)化公司,做網(wǎng)站 域名不屬于,定制軟件開發(fā)一、函數(shù)指針簡介 函數(shù)指針是指指向函數(shù)而非指向?qū)ο蟮闹羔?。像其他指針一?amp;#xff0c;函數(shù)指針也指向某個特定的類型。函數(shù)類型由其返回類型以及形參表確定,而與函數(shù)名無關(guān)。例如: char* (*pf1)(char * p1,char *p2); 這是一個函數(shù)指針,其…

一、函數(shù)指針簡介

????????函數(shù)指針是指指向函數(shù)而非指向?qū)ο蟮闹羔?。像其他指針一?#xff0c;函數(shù)指針也指向某個特定的類型。函數(shù)類型由其返回類型以及形參表確定,而與函數(shù)名無關(guān)。例如:

char* (*pf1)(char * p1,char *p2);

??????? 這是一個函數(shù)指針,其真實詞意如果轉(zhuǎn)換一下,似乎更好理解,只是編譯器不會這樣排版而已:

char* (*)(char * p1,char *p2) pf1;

??????? 將 pf 聲明為指向函數(shù)的指針,它所指向的函數(shù)帶有兩個 char* 類型的形參和 char*類型的返回值。注意*pf兩側(cè)的圓括號是必需的,否則就成了返回char**類型的普通函數(shù)聲明了。參數(shù)類型是必須的,但參數(shù)名不是必須的,可以省略。

char* (*pf1)(char*,char*); //char* (*)(char*,char*) pf1;

??????? 通常我們在開發(fā)中,尤其是應(yīng)用層級開發(fā)中,較少使用函數(shù)指針,也不建議使用函數(shù)指針。但是由于函數(shù)指針其特殊性,可以迸發(fā)出很多巧妙的代碼組織方法,尤其是很多底層驅(qū)動開發(fā)中,不少地方都會用到函數(shù)指針。

??????? 函數(shù)指針類型相當(dāng)?shù)厝唛L。使用 typedef 為指針類型定義同義詞,可將函數(shù)指針的使用大大簡化:

typedef char* (*pfunc)(char*, char*);

??????? 聲明函數(shù)指針后,需要給予初始化或賦值才能使用:

//先定義一個真實函數(shù)
char* fun1(char * p1,char *p2)
{return ((0== strcmp(p1,p2))?p1:p2);
};//char* (*pf1)(char*, char*) = &fun1;//直接初始化
char* (*pf1)(char*, char*);
pf1 = &fun1;	            //fun1等同于char* (*)(char*, char*)char p1[]="abc";
char p2[]="bcd";
printf("%s\n", (*pf1)(p1,p2));

??????? 函數(shù)名作為右值時,在引用函數(shù)名但又沒有調(diào)用該函數(shù)時,函數(shù)名將被自動解釋為指向函數(shù)的指針,因此采用&func或func給函數(shù)指針賦值都可以,以下四種中可以達(dá)成目的。

//func1除了用作函數(shù)調(diào)用的左操作數(shù)以外,對 fun1的任何使用都被解釋為char* (*)(char*, char*)
char* (*pf1)(char*, char*) = fun1;//直接初始化
char* (*pf2)(char*, char*) = &fun1;//直接初始化
char* (*pf3)(char*, char*);//
char* (*pf4)(char*, char*);//
pf3 = func1;
pf4 = &func1;
typedef char* (*pfunc)(char*, char*);
pfunc pf5 = fun1;						
pfunc pf6 = &fun1;						

????????函數(shù)指針只能通過同類型的函數(shù)或函數(shù)指針或 0 值常量表達(dá)式進(jìn)行初始化或賦值。

char* (*pf1)(char*, char*);
pf1 = &fun1;						
//
pfunc pf3 = 0;		//初始化為 0,表示該指針不指向任何函數(shù)
pf3 = pf1;char fun3(char * p1,char *p2)
{return ((0== strcmp(p1,p2))?p1:p2);
};char* fun4(char  p1,char p2)
{return ((0== strcmp(p1,p2))?p1:p2);
};pf3 = fun3;//eroor,返回類型不一致
pf3 = &fun4;//eroor,參數(shù)類型不一致

????????指向函數(shù)的指針可用于調(diào)用它所指向的函數(shù),支持顯式或隱式方式。

    char p1[]="abc";char p2[]="bcd";pfunc pf3 = fun1;printf("%s\n",pf3(p1,p2));		//隱式調(diào)用printf("%s\n",(*pf3)(p1,p2));	//顯式調(diào)用

二、函數(shù)指針數(shù)組

??????? 函數(shù)指針數(shù)組,就是將函數(shù)指針存儲在一個數(shù)組里,假設(shè)定義一個函數(shù)指針:

void (*FuncPtr)();

??????? 那么FuncPtr就是一個函數(shù)指針,既然 FuncPtr是一個指針,那就可以儲存在一個數(shù)組里。

void (*FuncPtr[])();
或
void (*FuncPtr[2])();

?????????定義一個函數(shù)指針數(shù)組。它是一個數(shù)組,數(shù)組名為 FuncPtr,數(shù)組內(nèi)存儲了 3 個或未知個數(shù)的指向函數(shù)的指針。這些指針指向一些返回值類型為void、無參數(shù)的函數(shù)。當(dāng)然也可以通過typedef 修飾一下,就像定義變量數(shù)組一樣:

typedef void (*FuncPtr)(); FuncPtr pfunc[3];

??????? 同樣,函數(shù)指針數(shù)組也要給其賦值,指向真實函數(shù)地址才能使用

typedef void (*FuncPtr)(); void doSomething1()
{printf("doSomething1\n");
};void doSomething2()
{printf("doSomething2\n");
};void (*fp[2])(); 
fp[0] = &doSomething1;
fp[1] = doSomething2;	
fp[0]();    //函數(shù)調(diào)用FuncPtr pfunc[2] = {doSomething1,doSomething2};
pfunc[0]();    //函數(shù)調(diào)用FuncPtr funcPtrArray[2];
funcPtrArray[0] = doSomething1;		//可以直接用函數(shù)名
funcPtrArray[1] = &doSomething2;	//可以用函數(shù)名加上取地址符
funcPtrArray[1]();    //函數(shù)調(diào)用

??????? 如果函數(shù)返回值有差異,但又想通過函數(shù)指針數(shù)組歸一化起來,在確保安全前提下,通過reinterpret_cast進(jìn)行函數(shù)指針類型轉(zhuǎn)換,注意c中是沒有reinterpret_cast的。

typedef void (*FuncPtr)(); int doSomething3()
{printf("doSomething3\n");return 0;
};FuncPtr funcPtrArray[3];
funcPtrArray[0] = doSomething1;		//可以直接用函數(shù)名
funcPtrArray[1] = &doSomething2;	//可以用函數(shù)名加上取地址符
//注意doSomething3直接傳遞是類型不符合的,它對于funcPtrArray是一個錯誤類型
//c++的reinterpret_cast 可以讓你迫使編譯器以你的方法去處理,
//轉(zhuǎn)換函數(shù)指針,C++不保證所有的函數(shù)指針都被用一樣的方法表示,在一些情況下這樣的轉(zhuǎn)換會產(chǎn)生不正確的結(jié)果.
funcPtrArray[2] = reinterpret_cast<FuncPtr>(&doSomething3);//g++編譯時生效

??????? c語言編譯時,可仿c++的reinterpret_cast創(chuàng)建一個類似的帶參宏定義

#define reinterpret_cast(TYPE,EXPR) ((TYPE)(EXPR))    //仿c++的reinterpret_cast
//此處省略聲明定義
funcPtrArray[2] = reinterpret_cast(FuncPtr, &doSomething3);//gcc或g++編譯時都生效
funcPtrArray[2]();

三、指向重載函數(shù)的指針

??????? C++語言允許使用函數(shù)指針指向重載的函數(shù),假設(shè)在func.cpp中定義了函數(shù)func_test

//func.cpp
int func_test(int p1, int p2)
{return (p1<p2)?p1:p2;
};

??????? 在test.cpp中通過extern實現(xiàn)重載。

//test.cpp
extern int func_test(int, int);//指向重載函數(shù)的指針
int (*pft)(int, int) = &func_test;
printf("min_val:%d\n", (*pft)(6,7));

????????注意指針的類型必須與重載函數(shù)的精確匹配。如果沒有精確匹配的函數(shù),則對該指針的初始化或賦值都將導(dǎo)致編譯錯誤:

//test.cpp
int (*pf2)(int) = &func_test;    //error,invalid parametervoid (*pf3)(int, int);
pf3 = &func_test;                // error, invalid return type

四、函數(shù)指針作為類成員

??????? 函數(shù)指針也是指針,既然是指針,就可以作為類成員變量來使用。

??????? 假設(shè)有如下類CallBack,其成員變量是一個函數(shù)指針CallBackPtr及void*的指針,初始化時傳遞一個函數(shù)指針和void變量指針實現(xiàn)初始化,通過doCallBack函數(shù)具體調(diào)用CallBackPtr實現(xiàn)函數(shù)回調(diào):

//在傳遞函數(shù)指針時,建議進(jìn)行這種異常規(guī)格的檢查
typedef void (*CallBackPtr)(void *data_);
class CallBack
{public:CallBack(CallBackPtr fPtr, void *data_): func(fPtr), data(data_) {}void doCallBack() const throw();
private:CallBackPtr func; 	// function to call when// callback is madevoid *data; 		// data to pass to callback
}; void CallBack::doCallBack() const throw()
{func(data);
}

??????? 該類使用時,定義具體業(yè)務(wù)實現(xiàn)的真實函數(shù),將這些函數(shù)指針傳遞給CallBack類,業(yè)務(wù)實際需要滯后到實現(xiàn)具體業(yè)務(wù)場景明確時,實現(xiàn)其邏輯,如下:


void callBackFcn1(void *data_)
{printf("callBackFcn1\n");
};void callBackFcn2(void *data_) throw()
{printf("callBackFcn2\n");
};
//回調(diào),將具體實現(xiàn)放置構(gòu)造傳遞進(jìn)去的具體函數(shù)指針
void *callBackData;
CallBack c_instance(callBackFcn1,callBackData);
c_instance.doCallBack();

??????? 在傳遞函數(shù)指針時,建議進(jìn)行這種異常規(guī)格的檢查,大家可以想想如下函數(shù)指針定義時,指向的真實函數(shù)定義該如何設(shè)計。

typedef void (*CallBackPtr)(void *data_) throw();//如果不提供異常說明,該指針就可以指向能夠拋出任意類型異常的具有匹配類型的函數(shù)
typedef void (*CallBackPtr)(void *data_) throw(runtime_error);//指定異常時,只能拋出 runtime_error 類型的異常
typedef void (*CallBackPtr)(void *data_) const throw();//類型定義更嚴(yán)格,源指針的異常說明必須至少與目標(biāo)指針的一樣嚴(yán)格

五、函數(shù)指針作為形參

????????函數(shù)指針也是指針,既然是指針,就可以作為參數(shù)傳遞給函數(shù),函數(shù)就可以在其內(nèi)部使用該函數(shù)指針,從而實現(xiàn)對函數(shù)指針指向的函數(shù)進(jìn)行調(diào)用,實現(xiàn)函數(shù)回調(diào)。想STL標(biāo)準(zhǔn)了內(nèi)的排序函數(shù) 模板就是通過傳遞一個數(shù)值比較的函數(shù)指針來實現(xiàn)的。

//函數(shù)指針作為形參
class Aclass
{	
public:Aclass(void* data_) : vdata(data_){};void doSomething1(){printf("Aclass doSomething1\n");};void doSomething2(){printf("Aclass doSomething2\n");};void* getData(){return vdata;}
private:void* vdata;
};void myfunc(Aclass* ptr,void* data,bool (*compare)(void const* pd1, void const* pd2))
{if(compare(ptr->getData(),data))ptr->doSomething1();elseptr->doSomething2();
};bool compare_int(void const* pd1, void const* pd2)
{return (*(int*)pd1=*(int*)pd2)?false:true;
}

??????? 如上述代碼,myfunc函數(shù)參數(shù)很復(fù)雜,將類對象,數(shù)值及函數(shù)指針作為參數(shù)傳遞進(jìn)去。函數(shù)指針通過重定義一下:

typedef bool (*Func_compare)(void const* pd1, void const* pd2);void myfunc(Aclass* ptr,void* data,Func_compare compare);

??????? 函數(shù)調(diào)用如下:

int aval = 10;
int bval = 8;
Aclass a_obj(&aval);
myfunc(&a_obj,&bval,compare_int);	//

六、 轉(zhuǎn)換表

??????? 有以下一種功能要求,這是一個實現(xiàn)操作符計算的分支設(shè)計,如果有上百個操作符需要實現(xiàn)呢,這個switch語句就會很長:

switch(oper)
{case ADD:ret = add(val1,val2);break;case SUB:ret = sub(val1,val2);break;case MUL:ret = mul(val1,val2);break;case DIV:ret = div(val1,val2);break;......default:ret = 0.0;break;
}

??????? 通過建立一個函數(shù)指針數(shù)組作為轉(zhuǎn)換表,就可以實現(xiàn)類似switch的代碼功能:

enum Method{ADD=0,SUB,MUL,DIV
};typedef float (*operFunc)(float fa, float fb);operFunc operf[] = {add,sub,mul,div};

??????? 其調(diào)用如下,確保這些操作符函數(shù)定義在初始化列表之前,初始化列表的函數(shù)名順序取決與程序用來表示每個操作符的整型代碼。

//操作符具體實現(xiàn)函數(shù)
float add(float fa, float fb)
{return fa+fb;
};
float sub(float fa, float fb)
{return fa-fb;
};
float mul(float fa, float fb)
{return fa*fb;
};const float abs_min_val = 0.0000001;
float div(float fa, float fb)
{if((fb<abs_min_val)&&(fb>(-abs_min_val))){return fa/abs_min_val;}return fa/fb;
};
//函數(shù)指針數(shù)組調(diào)用,實現(xiàn)類switch功能
float afval = 7.8, bfval = 8.5;
float ret_fval = operf[Method::ADD](afval,bfval);
printf("%0.4f\n",ret_fval);

七、類函數(shù)指針成員與注冊函數(shù)

??????? 函數(shù)指針是指針,就可以作為類的成員變量,通常用于將具體業(yè)務(wù)實現(xiàn)剝離在類外定義實現(xiàn),在業(yè)務(wù)執(zhí)行是注冊到類中,從而針對具體業(yè)務(wù)來調(diào)用需要的業(yè)務(wù)模塊(業(yè)務(wù)函數(shù))。

//函數(shù)指針成員,注冊函數(shù)
class BClass
{
public:BClass(){my_compare = NULL;};typedef bool (*compare)(void const* pd1, void const* pd2);void my_compare_do(void const* cm1, void const* cm2)    //具體實現(xiàn)通過調(diào)用外部函數(shù){if(NULL==my_compare)printf("please register func first!\n");if(my_compare(cm1,cm2))    //外部函數(shù)調(diào)用printf("do it A\n");elseprintf("do it B\n");};void register_func(compare cp1)    //注冊函數(shù){my_compare = cp1;};compare my_compare;	//函數(shù)指針變量
};

??????? 在具體業(yè)務(wù)邏輯過程中,先給類實例注入調(diào)用函數(shù),在調(diào)用具體函數(shù)實現(xiàn)業(yè)務(wù)邏輯。

	//注冊函數(shù),實現(xiàn)外部函數(shù)調(diào)用BClass bObject;bObject.register_func(compare_int);bObject.my_compare_do(&aval,&bval);

八、類函數(shù)指針數(shù)組

??????? 同樣地,函數(shù)指針還可以通過函數(shù)指針數(shù)組作為類成員列表,這些成員的實現(xiàn)細(xì)節(jié)當(dāng)然是可以在類內(nèi)部,外部或外部模塊來具體實現(xiàn)。例如,在很多程序會這樣做,在程序中的每個類只要聲明函數(shù)指針數(shù)組,然后在外部來具體實現(xiàn)業(yè)務(wù),甚至是交給二次開發(fā)者依據(jù)具體業(yè)務(wù)場景來針對性設(shè)計功能函數(shù)。

//類函數(shù)指針數(shù)組test(成員列表)
class OperateKey
{
public:OperateKey(){};enum Directions { FORWARD, BACK, UP, DOWN };OperateKey& do_it(Directions direct_){ //記需要有效性判斷(this->vtbl[direct_])();return *this;};typedef void (*Action)();static Action vtbl[];
};void forward()
{printf("forward\n");
};
void  back()
{printf("back\n");
};
void up()
{printf("up\n");
};
void down()
{printf("down\n");
};OperateKey::Action OperateKey::vtbl[] = {forward, back, up, down};

???????? 類的函數(shù)指針數(shù)組成員列表就像平常類實例使用數(shù)組變量一樣使用即可,只是數(shù)組變量是作為變量使用,而函數(shù)指針數(shù)組存儲的是函數(shù)名(函數(shù)地址),作為一個個函數(shù)使用。

    //類函數(shù)指針數(shù)組成員列表OperateKey myKeys;myKeys.do_it(OperateKey::FORWARD);myKeys.do_it(OperateKey::DOWN);

九、函數(shù)指針測試案例

??????? 創(chuàng)建test.cpp和func.cpp文件,主要是代碼是在test.cpp中實現(xiàn)。

??????? func.cpp,用來測試函數(shù)指針重載

//
int func_test(int p1, int p2)
{return (p1<p2)?p1:p2;
};

??????? test.cpp

#include <string.h>
#include <stdio.h>//函數(shù)指針test
char* fun1(char * p1,char *p2)
{return ((0== strcmp(p1,p2))?p1:p2);
};char* fun2(char * p1,char *p2)
{return ((0== strcmp(p1,p2))?p2:p1);
};typedef char* (*pfunc)(char*, char*);//函數(shù)指針數(shù)組test
typedef void (*FuncPtr)(); #define reinterpret_cast(TYPE,EXPR) ((TYPE)(EXPR))void doSomething1()
{printf("doSomething1\n");
};void doSomething2()
{printf("doSomething2\n");
};int doSomething3()
{printf("doSomething3\n");return 0;
};
//
extern int func_test(int, int);
//回調(diào)
//在傳遞函數(shù)指針時,建議進(jìn)行這種異常規(guī)格的檢查
typedef void (*CallBackPtr)(void *data_);
//typedef void (*CallBackPtr)(void *data_) throw();?//如果不提供異常說明,該指針就可以指向能夠拋出任意類型異常的具有匹配類型的函數(shù)
//typedef void (*CallBackPtr)(void *data_) throw(runtime_error);?//指定異常時,只能拋出 runtime_error 類型的異常
//typedef void (*CallBackPtr)(void *data_) const throw();?//類型定義更嚴(yán)格,源指針的異常說明必須至少與目標(biāo)指針的一樣嚴(yán)格
class CallBack
{public:CallBack(CallBackPtr fPtr, void *data_): func(fPtr), data(data_) {}void doCallBack() const throw();
private:CallBackPtr func; 	// function to call when// callback is madevoid *data; 		// data to pass to callback
}; void CallBack::doCallBack() const throw()
{func(data);
}void callBackFcn1(void *data_)
{printf("callBackFcn1\n");
};void callBackFcn2(void *data_) throw()
{printf("callBackFcn2\n");
};//函數(shù)指針作為形參
class Aclass
{	
public:Aclass(void* data_) : vdata(data_){};void doSomething1(){printf("Aclass doSomething1\n");};void doSomething2(){printf("Aclass doSomething2\n");};void* getData(){return vdata;}
private:void* vdata;
};void myfunc(Aclass* ptr,void* data,bool (*compare)(void const* pd1, void const* pd2))
{if(compare(ptr->getData(),data))ptr->doSomething1();elseptr->doSomething2();
};bool compare_int(void const* pd1, void const* pd2)
{return (*(int*)pd1=*(int*)pd2)?false:true;
}
//
float add(float fa, float fb)
{return fa+fb;
};
float sub(float fa, float fb)
{return fa-fb;
};
float mul(float fa, float fb)
{return fa*fb;
};const float abs_min_val = 0.0000001;
float div(float fa, float fb)
{if((fb<abs_min_val)&&(fb>(-abs_min_val))){return fa/abs_min_val;}return fa/fb;
};typedef float (*operFunc)(float fa, float fb);enum Method{ADD=0,SUB,MUL,DIV
};
//函數(shù)指針成員,注冊函數(shù)
class BClass
{
public:BClass(){my_compare = NULL;};typedef bool (*compare)(void const* pd1, void const* pd2);void my_compare_do(void const* cm1, void const* cm2){if(NULL==my_compare)printf("please register func first!\n");if(my_compare(cm1,cm2))printf("do it A\n");elseprintf("do it B\n");};void register_func(compare cp1){my_compare = cp1;};compare my_compare;	
};//類函數(shù)指針數(shù)組test(成員列表)
class OperateKey
{
public:OperateKey(){};enum Directions { FORWARD, BACK, UP, DOWN };OperateKey& do_it(Directions direct_){(this->vtbl[direct_])();return *this;};typedef void (*Action)();static Action vtbl[];
};void forward()
{printf("forward\n");
};
void  back()
{printf("back\n");
};
void up()
{printf("up\n");
};
void down()
{printf("down\n");
};OperateKey::Action OperateKey::vtbl[] = {forward, back, up, down};int main(int argc, char* argv[])
{//char* (*pf1)(char * p1,char *p2);//定義一個函數(shù)指針變量,等同于下一句char* (*pf1)(char*, char*);char p1[]="abc";char p2[]="bcd";//char* (*pf1)(char*, char*) = &fun1;//直接初始化pf1 = &fun1;						//fun等同于char* (*)(char*, char*)printf("%s\n", (*pf1)(p1,p2));pfunc pf2=fun2;printf("%s\n",(*pf2)(p1,p2));//pfunc pf3 = 0;		//初始化為 0,表示該指針不指向任何函數(shù)pf3 = pf1;printf("%s\n",pf3(p1,p2));		//隱式調(diào)用pf3 = pf2;printf("%s\n",(*pf3)(p1,p2));	//顯式調(diào)用//FuncPtr pfuncs[2] = {doSomething1,doSomething2};FuncPtr funcPtrArray[3];funcPtrArray[0] = doSomething1;		//可以直接用函數(shù)名funcPtrArray[1] = &doSomething2;	//可以用函數(shù)名加上取地址符//注意doSomething3直接傳遞是類型不符合的,它對于funcPtrArray是一個錯誤類型//c++的reinterpret_cast 可以讓你迫使編譯器以你的方法去處理,//轉(zhuǎn)換函數(shù)指針,C++不保證所有的函數(shù)指針都被用一樣的方法表示,在一些情況下這樣的轉(zhuǎn)換會產(chǎn)生不正確的結(jié)果.//funcPtrArray[2] = reinterpret_cast<FuncPtr>(&doSomething3);//g++編譯時生效funcPtrArray[2] = reinterpret_cast(FuncPtr, &doSomething3);//gcc或g++編譯時都生效for(int i=0; i<3; i++){funcPtrArray[i]();}//指向重載函數(shù)的指針int (*pft)(int, int) = &func_test;printf("min_val:%d\n", (*pft)(6,7));//回調(diào)void *callBackData;CallBack c_instance(callBackFcn1,callBackData);c_instance.doCallBack();//int aval = 10;int bval = 8;Aclass a_obj(&aval);myfunc(&a_obj,&bval,compare_int);	////operFunc operf[] = {add,sub,mul,div};float afval = 7.8, bfval = 8.5;float ret_fval = operf[Method::ADD](afval,bfval);printf("%0.4f\n",ret_fval);//注冊函數(shù)BClass bObject;bObject.register_func(compare_int);bObject.my_compare_do(&aval,&bval);//類函數(shù)指針數(shù)組成員列表OperateKey myKeys;myKeys.do_it(OperateKey::FORWARD);myKeys.do_it(OperateKey::DOWN);return 0;
}

??????? 編譯

g++ test.cpp func.cpp -o test.exe

??????? 或者構(gòu)建Makefile文件,調(diào)用make指令

CX	=	g++BIN 		:= .
TARGET      := test.exe
FLAGS		:= Include		:= .
source		:= test.cpp func.cpp
$(TARGET) :$(CX) $(FLAGS) $(source) -I$(Include) -o $(BIN)/$(TARGET)clean:rm  $(BIN)/$(TARGET)

??????? 測試程序運行輸出如下:

http://aloenet.com.cn/news/39272.html

相關(guān)文章:

  • 網(wǎng)絡(luò)代理是干嘛的重慶seo扣費
  • 廣州站桂平網(wǎng)絡(luò)推廣
  • 宿遷建設(shè)局網(wǎng)站win7系統(tǒng)優(yōu)化
  • 禪城網(wǎng)站建設(shè)多少錢網(wǎng)絡(luò)營銷推廣策劃的步驟是什么
  • 高端營銷網(wǎng)站泰州百度公司代理商
  • 代做ppt網(wǎng)站百度知道在線問答
  • 網(wǎng)站靜態(tài)頁面網(wǎng)絡(luò)營銷案例ppt
  • 鹽亭做網(wǎng)站采集站seo提高收錄
  • 研發(fā)一個app費用seo百度發(fā)包工具
  • 深圳有做網(wǎng)站公司十大計算機培訓(xùn)學(xué)校
  • 綿陽做網(wǎng)站優(yōu)化杭州百度開戶
  • 微信上的小說網(wǎng)站是怎么做的做網(wǎng)絡(luò)推廣要學(xué)些什么
  • 找建設(shè)網(wǎng)站公司seo技術(shù)優(yōu)化服務(wù)
  • 合肥響應(yīng)式網(wǎng)站開發(fā)方案網(wǎng)絡(luò)推廣需要什么
  • 注冊過什么網(wǎng)站經(jīng)典軟文案例和扶貧農(nóng)產(chǎn)品軟文
  • 網(wǎng)站模塊是指什么地方石家莊線上推廣平臺
  • 網(wǎng)站建設(shè)論團seo網(wǎng)站推廣報價
  • jsp做網(wǎng)站遇到的問題獨立站seo
  • 寶安網(wǎng)站開發(fā)百度平臺我的訂單查詢在哪里
  • 海口今天發(fā)現(xiàn)一例東莞網(wǎng)站優(yōu)化
  • 做資源下載網(wǎng)站用什么工具山東建站管理系統(tǒng)
  • 網(wǎng)頁制作三劍客教程品牌詞優(yōu)化
  • php動態(tài)網(wǎng)站開發(fā)第四章企業(yè)seo關(guān)鍵詞優(yōu)化
  • 做網(wǎng)站的客戶資料交換qq群北京sem
  • 網(wǎng)站商城建設(shè)如何避免內(nèi)部競爭百度網(wǎng)絡(luò)營銷推廣
  • 沈陽教做網(wǎng)站市場營銷策劃
  • 網(wǎng)站上圖怎么用ps做阿里云服務(wù)器
  • 常寧做網(wǎng)站百度app營銷軟件
  • 怎么自己學(xué)著做網(wǎng)站網(wǎng)站運營seo實訓(xùn)總結(jié)
  • 廣州做網(wǎng)站比較好的公司官網(wǎng)seo