多態(tài)就是完成某個(gè)行為時(shí),不同對(duì)象去完成時(shí)會(huì)產(chǎn)生不同的狀態(tài)。
比如買(mǎi)票,普通人買(mǎi)全價(jià)票,學(xué)生買(mǎi)半價(jià)票,軍人優(yōu)先買(mǎi)票。
多態(tài)是在不同繼承關(guān)系的類(lèi)對(duì)象,去調(diào)用同一函數(shù),產(chǎn)生不同的行為。
繼承中構(gòu)成多態(tài)還有兩個(gè)條件:
1.必須通過(guò)基類(lèi)的指針或引用去調(diào)用虛函數(shù);
2.被調(diào)用的函數(shù)必須是虛函數(shù),且派生類(lèi)必須對(duì)基類(lèi)的虛函數(shù)進(jìn)行重寫(xiě);
用virtual關(guān)鍵字修飾的成員函數(shù)就是虛函數(shù)。
代碼如下:
class Person
{public:
virtual void BuyTicket()
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
}
};
3、虛函數(shù)的重寫(xiě)派生類(lèi)中的虛函數(shù)構(gòu)成重寫(xiě)(覆蓋)的條件有:函數(shù)名、參數(shù)和返回值類(lèi)型相同,但是函數(shù)的實(shí)現(xiàn)不同;
如果不構(gòu)成重寫(xiě),就是隱藏關(guān)系;
代碼如下:
class Person
{public:
virtual void BuyTicket()
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
}
};
class Student : public Person
{public:
virtual void BuyTicket()
{cout<< "買(mǎi)票 - 半價(jià)"<< endl; //重寫(xiě)
}
};
class Soldier : public Person
{public:
virtual void BuyTicket()
{cout<< "買(mǎi)票 - 優(yōu)先"<< endl; //重寫(xiě)
}
};
void Func(Person& p) //使用父類(lèi)的引用調(diào)用虛函數(shù)
{p.BuyTicket();
}
void Test()
{Person p;
Func(p);
Student st;
Func(st);
Soldier sd;
Func(sd);
}
以上代碼就完整的構(gòu)成了多態(tài),其運(yùn)行效果為:
不同的對(duì)象調(diào)用同一個(gè)虛函數(shù),呈現(xiàn)出了不同的效果。
1.將子類(lèi)中虛函數(shù)的virtual去掉
class Person
{public:
virtual void BuyTicket()
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
}
};
class Student : public Person
{public:
void BuyTicket()
{cout<< "買(mǎi)票 - 半價(jià)"<< endl;
}
};
這樣依然構(gòu)成重寫(xiě),子類(lèi)中依然是虛函數(shù),編譯器認(rèn)為先把父類(lèi)的虛函數(shù)繼承下來(lái)了,而且是接口繼承,將函數(shù)接口完整繼承下來(lái)了,子類(lèi)中只是將函數(shù)的實(shí)現(xiàn)進(jìn)行重寫(xiě)。
2.重寫(xiě)的協(xié)變
返回值類(lèi)型可以不同,要求必須是父子關(guān)系的指針或引用;
代碼如下:
class Person
{public:
virtual Person* BuyTicket()
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
}
};
class Student : public Person
{public:
virtual void BuyTicket()
{cout<< "買(mǎi)票 - 半價(jià)"<< endl;
}
};
以上的代碼是會(huì)報(bào)錯(cuò)的,因?yàn)橹粷M足了返回值類(lèi)型不同,并不是父子關(guān)系的指針或引用,下面的代碼才是協(xié)變:
class Person
{public:
virtual Person* BuyTicket()
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
return this;
}
};
class Student : public Person
{public:
virtual Student* BuyTicket() //返回值是有父子關(guān)系的指針或引用
{cout<< "買(mǎi)票 - 半價(jià)"<< endl;
return this;
}
};
運(yùn)行結(jié)果為:
上面的代碼依然能夠構(gòu)成多態(tài)。
3.析構(gòu)函數(shù)的重寫(xiě)
建議在繼承中將析構(gòu)函數(shù)定義為虛函數(shù);
class Person
{public:
virtual ~Person()
{cout<< "~Person()"<< endl;
}
};
class Student : public Person
{public:
virtual ~Student() //子類(lèi)的析構(gòu)函數(shù)與父類(lèi)的析構(gòu)函數(shù)的函數(shù)名并不相同
{cout<< "~Student()"<< endl;
}
};
int main()
{Person* p1 = new Person;
delete p1;
Person* p2 = new Student;//父類(lèi)指針指向子類(lèi)對(duì)象,符合多態(tài)調(diào)用
delete p2;
return 0;
}
以上代碼的運(yùn)行結(jié)果為:
子類(lèi)和父類(lèi)的析構(gòu)函數(shù),參數(shù)類(lèi)型和返回值類(lèi)型都相同,編譯器為了讓他們構(gòu)成重寫(xiě),將析構(gòu)函數(shù)名改寫(xiě)為destructor,所以,上述代碼中析構(gòu)函數(shù)完成了重寫(xiě)。
只有子類(lèi)析構(gòu)函數(shù)重寫(xiě)了父類(lèi)的析構(gòu)函數(shù),這里才能正確調(diào)用,指針指向父類(lèi)對(duì)象,調(diào)用父類(lèi)的析構(gòu)函數(shù),指向子類(lèi)對(duì)象就調(diào)用子類(lèi)的析構(gòu)函數(shù)。
如果析構(gòu)函數(shù)不是虛函數(shù):
class Person
{public:
~Person()
{cout<< "~Person()"<< endl;
}
};
class Student : public Person
{public:
~Student() //子類(lèi)的析構(gòu)函數(shù)與父類(lèi)的析構(gòu)函數(shù)的函數(shù)名并不相同
{cout<< "~Student()"<< endl;
}
};
int main()
{Person* ptr1 = new Person;
delete ptr1;
Person* ptr2 = new Student;//父類(lèi)指針指向子類(lèi)對(duì)象,符合多態(tài)調(diào)用
delete ptr2;
return 0;
}
在子類(lèi)delete時(shí),調(diào)用的還是父類(lèi)的析構(gòu)函數(shù):
這里是普通調(diào)用,不符合多態(tài),在編譯時(shí)就決定了;
ptr2是Person*類(lèi)型的指針,call的是Person的析構(gòu)函數(shù);
ptr1希望調(diào)用父類(lèi)的析構(gòu),ptr2希望調(diào)用子類(lèi)的析構(gòu),所以把析構(gòu)設(shè)計(jì)成符合多態(tài)的函數(shù)名。
1.不是父類(lèi)的指針或引用調(diào)用虛函數(shù)
代碼如下:
class Person
{public:
virtual void BuyTicket()
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
}
};
class Student : public Person
{public:
virtual void BuyTicket()
{cout<< "買(mǎi)票 - 半價(jià)"<< endl;
}
};
void Func(Person p)
{p.BuyTicket();
}
運(yùn)行結(jié)果為:
上述代碼是不構(gòu)成多態(tài)的。
2.不符合虛函數(shù)重寫(xiě)
2.1將父類(lèi)虛函數(shù)的virtual去掉
class Person
{public:
void BuyTicket()
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
}
};
class Student : public Person
{public:
virtual void BuyTicket()
{cout<< "買(mǎi)票 - 半價(jià)"<< endl;
}
};
void Func(Person& p)
{p.BuyTicket();
}
運(yùn)行結(jié)果為:
是不符合虛函數(shù)重寫(xiě)的,自然就不構(gòu)成多態(tài)。
2.2參數(shù)類(lèi)型不同
class Person
{public:
void BuyTicket(char)
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
}
};
class Student : public Person
{public:
virtual void BuyTicket(int)
{cout<< "買(mǎi)票 - 半價(jià)"<< endl;
}
};
void Func(Person& p)
{p.BuyTicket();
}
運(yùn)行結(jié)果為:
同樣不符合多態(tài)。
1.final:修飾虛函數(shù),表示其不能再被重寫(xiě)(用的很少)
class Person
{public:
virtual void BuyTicket() final
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
}
};
class Student : public Person
{public:
virtual void BuyTicket()
{cout<< "買(mǎi)票 - 半價(jià)"<< endl;
}
};
編譯之后會(huì)報(bào)錯(cuò):
2.override:檢查派生類(lèi)虛函數(shù)是否重寫(xiě)了某個(gè)基類(lèi)的虛函數(shù),若沒(méi)有重寫(xiě)編譯報(bào)錯(cuò)(常用)
class Person
{public:
virtual void BuyTicket(int)
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
}
};
class Student : public Person
{public:
virtual void BuyTicket(char) override//參數(shù)類(lèi)型不一致,未完成重寫(xiě)
{cout<< "買(mǎi)票 - 全價(jià)"<< endl;
}
};
上述代碼子類(lèi)的虛函數(shù)未完成重寫(xiě),在后面加了override后,編譯器就會(huì)報(bào)錯(cuò):
override常用于檢查子類(lèi)虛函數(shù)重寫(xiě)的語(yǔ)法是否正確。
代碼如下:
#includeusing namespace std;
class A
{public:
virtual void func(int val = 1)
{cout<< "A ->"<< val<< endl;
}
virtual void test()
{func();
}
};
class B : public A
{public:
virtual void func(int val = 0)
{cout<< "B ->"<< val<< endl;
}
};
int main()
{B* p = new B;
p->test();
return 0;
}
以上代碼的輸出結(jié)果為:
分析:
如果將代碼改成以下形式:
class A
{public:
virtual void func(int val)//去掉缺省值
{cout<< "A ->"<< val<< endl;
}
virtual void test()
{func(1);
}
};
class B : public A
{public:
void func(int val)
{cout<< "B ->"<< val<< endl;
}
};
int main()
{//Test();
A* p = new B;//用父類(lèi)的指針指向子類(lèi)對(duì)象
p->test();
return 0;
}
子類(lèi)和父類(lèi)的func依然構(gòu)成虛函數(shù)重寫(xiě);
這里用父類(lèi)的指針指向子類(lèi)對(duì)象,發(fā)生了切片,但指向的還是子類(lèi)的對(duì)象,所以調(diào)用的函數(shù)還是子類(lèi)中的虛函數(shù),結(jié)果還是:B ->1;
最終結(jié)果與p的指針類(lèi)型無(wú)關(guān),只與它指向的對(duì)象有關(guān)。
在虛函數(shù)的后面寫(xiě)上 = 0,這個(gè)函數(shù)就是純虛函數(shù),包含純虛函數(shù)的類(lèi)叫做抽象類(lèi)(接口類(lèi)),抽象類(lèi)不能實(shí)例化出對(duì)象,派生類(lèi)繼承抽象類(lèi)后也不能實(shí)例化出對(duì)象,只有派生類(lèi)重寫(xiě)了虛函數(shù),才能實(shí)例化對(duì)象,純虛函數(shù)規(guī)范了派生類(lèi)必須重寫(xiě),更好的體現(xiàn)出了接口繼承。
代碼如下:
class Car //把不想實(shí)例化出對(duì)象的父類(lèi)定義為抽象類(lèi)
{public:
virtual void Drive() = 0;
};
class Benz : public Car
{public:
virtual void Drive(int) //如果子類(lèi)繼承了抽象類(lèi)卻未完成虛函數(shù)重寫(xiě),就會(huì)報(bào)錯(cuò)
{cout<< "Benz - 舒適"<< endl;
}
};
class BMW : public Car
{public:
virtual void Drive()
{cout<< "BMW - 操控"<< endl;
}
};
int main()
{Car c1;
Benz c2;
BMW c3;
return 0;
}
1.抽象類(lèi)一般用于定義接口,將不想實(shí)例化出對(duì)象的類(lèi)定義為抽象類(lèi);
2.抽象函數(shù)強(qiáng)制子類(lèi)完成虛函數(shù)的重寫(xiě),不重寫(xiě)就無(wú)法實(shí)例化,而override是檢查語(yǔ)法是否完成重寫(xiě);
創(chuàng)建如下對(duì)象:
class Base
{public:
virtual void func()
{cout<< "func"<< endl;
}
private:
int _b = 0;
};
int main()
{Base b;
cout<< sizeof(b)<< endl;
return 0;
}
我么可以發(fā)現(xiàn)sizeof(b)的結(jié)果是8,再看b對(duì)象實(shí)例化后的成員
可以發(fā)現(xiàn)在成員_b的上面還有一個(gè)_vfptr的成員,這叫做虛函數(shù)表指針;帶有虛函數(shù)的類(lèi)對(duì)象,其成員中都有一個(gè)虛函數(shù)表指針,因?yàn)檫x虛函數(shù)要放到虛函數(shù)表中,也簡(jiǎn)稱虛表。
將Base繼承給子類(lèi),代碼如下:
class Base
{public:
virtual void func1()
{cout<< "Base::func1"<< endl;
}
virtual void func2() //加一個(gè)虛函數(shù)func2
{cout<< "Base::func2"<< endl;
}
void func3() //加一個(gè)普通函數(shù)func3
{cout<< "Base::func3"<< endl;
}
private:
int _b = 1;
};
class Derive : public Base
{public:
virtual void func1() //重寫(xiě)父類(lèi)虛函數(shù)
{cout<< "Derive::func1"<< endl;
}
private:
int _d = 2;
};
int main()
{Base b;
cout<< sizeof(b)<< endl;
Derive d;
return 0;
}
通過(guò)監(jiān)視窗口我們可以看到:
1.子類(lèi)對(duì)象d中也有一個(gè)虛函數(shù)表指針,且和父類(lèi)對(duì)象b的虛表指針不同,由于子類(lèi)對(duì)func1完成了重寫(xiě),虛表中的func1就是子類(lèi)重寫(xiě)后的Detive::func1;
2.func2是虛函數(shù),繼承下來(lái)也會(huì)放進(jìn)子類(lèi)的虛表,而func3不是虛函數(shù),不會(huì)放進(jìn)虛表;
3.虛表本身是一個(gè)放函數(shù)指針的數(shù)組,一般情況最后會(huì)放一個(gè)nullptr(vs環(huán)境下);
4.虛表存放的是虛函數(shù)的函數(shù)指針,不是虛函數(shù),虛函數(shù)跟普通函數(shù)一樣,都存放在代碼段。
通過(guò)對(duì)匯編代碼的分析,我們可以總結(jié)出:
1.滿足多態(tài)以后的函數(shù)調(diào)用,不是在編譯時(shí)確定的,是運(yùn)行起來(lái)以后再到對(duì)象中找的,程序運(yùn)行時(shí)取對(duì)象中的虛表指針找到函數(shù)地址,再去調(diào)用;
2.普通函數(shù)的調(diào)用,是在編譯鏈接時(shí)就確定函數(shù)的地址,運(yùn)行時(shí)直接調(diào)用。
代碼如下:
class Base
{public:
virtual void func1()
{cout<< "Base::func1"<< endl;
}
virtual void func2()
{cout<< "Base::func2"<< endl;
}
private:
int _b = 1;
};
class Derive : public Base
{public:
virtual void func1()
{cout<< "Derive::func1"<< endl;
}
virtual void func3()
{cout<< "Derive::func3"<< endl;
}
virtual void func4()
{cout<< "Derive::func4"<< endl;
}
private:
int _d = 2;
};
通過(guò)監(jiān)視窗口看不見(jiàn)func3和func4,我們可以使用代碼打印虛表中的函數(shù):
class Base
{public:
virtual void func1()
{cout<< "Base::func1"<< endl;
}
virtual void func2()
{cout<< "Base::func2"<< endl;
}
private:
int _b = 1;
};
class Derive : public Base
{public:
virtual void func1()
{cout<< "Derive::func1"<< endl;
}
virtual void func3()
{cout<< "Derive::func3"<< endl;
}
virtual void func4()
{cout<< "Derive::func4"<< endl;
}
private:
int _d = 2;
};
typedef void(*VFPTR) (); //將指向返回值為void、沒(méi)有參數(shù)的類(lèi)型的函數(shù)的指針重定義為VFPTR
void PrintVTable(VFPTR vTable[])
{//依次取虛表中的指針打印并調(diào)用,調(diào)用就可以看出存的是哪個(gè)函數(shù)
cout<< "虛表地址>"<< vTable<< endl;
for (int i = 0; vTable[i] != nullptr; i++)
{printf("第%d個(gè)虛函數(shù)地址:0x%x", i, vTable[i]);//打印地址
VFPTR f = vTable[i];//用函數(shù)指針取出虛函數(shù)地址
f();//調(diào)用
}
cout<< endl;
}
int main()
{Base b1;
Base b2;
Derive d;
VFPTR* vTableb1 = (VFPTR*)(*((int*)&b1));//將b對(duì)象的地址取出,強(qiáng)轉(zhuǎn)成int*,再解引用,就取出了b的頭四個(gè)字節(jié)的數(shù)據(jù),這個(gè)就是指向虛表的指針
//再?gòu)?qiáng)轉(zhuǎn)成VFPTR*,因?yàn)樘摫砭褪荲FPTR類(lèi)型的數(shù)組
PrintVTable(vTableb1);
VFPTR* vTableb2 = (VFPTR*)(*((int*)&b2));
PrintVTable(vTableb2);
VFPTR* vTabled = (VFPTR*)(*((int*)&d));
PrintVTable(vTabled);
return 0;
}
我么可以看出,在vs下:
1.同一個(gè)類(lèi)型的對(duì)象,共用一個(gè)虛表(b1和b2);
2.不管是否完成重寫(xiě)名子類(lèi)虛表和父類(lèi)虛表都不是同一個(gè);
3.單繼承中,子類(lèi)的所有虛函數(shù),包括重寫(xiě)父類(lèi)的虛函數(shù)和未重寫(xiě)的虛函數(shù),都放在同一個(gè)虛表中。
代碼如下:
class Base1
{public:
virtual void func1()
{cout<< "Base1::func1"<< endl;
}
virtual void func2()
{cout<< "Base1::func2"<< endl;
}
private:
int _b1 = 1;
};
class Base2
{public:
virtual void func1()
{cout<< "Base2::func1"<< endl;
}
virtual void func2()
{cout<< "Base2::func2"<< endl;
}
private:
int _b2 = 2;
};
class Derive : public Base1, public Base2
{public:
virtual void func1()
{cout<< "Derive::func1"<< endl;
}
virtual void func3()
{cout<< "Derive::func3"<< endl;
}
private:
int _d = 3;
};
typedef void(*VFPTR) (); //將指向返回值為void、沒(méi)有參數(shù)的類(lèi)型的函數(shù)的指針重定義為VFPTR
void PrintVTable(VFPTR vTable[])
{//依次取虛表中的指針打印并調(diào)用,調(diào)用就可以看出存的是哪個(gè)函數(shù)
cout<< "虛表地址>"<< vTable<< endl;
for (int i = 0; vTable[i] != nullptr; i++)
{printf("第%d個(gè)虛函數(shù)地址:0x%x", i, vTable[i]);//打印地址
VFPTR f = vTable[i];//用函數(shù)指針取出虛函數(shù)地址
f();//調(diào)用
}
cout<< endl;
}
int main()
{Derive d;
VFPTR* vTabled1 = (VFPTR*)(*((int*)&d));
PrintVTable(vTabled1);
VFPTR* vTabled2 = (VFPTR*)(*(int*)((char*)&d + sizeof(Base1)));//從Base2的虛表中取虛函數(shù)地址
PrintVTable(vTabled2);
return 0;
}
Derive多繼承Base1和Base2,其中Derive重寫(xiě)了func1,而func1既是Base1的虛函數(shù),也是Base2的虛函數(shù),func3是Derive自己的虛函數(shù),運(yùn)行結(jié)果如下:
可以看出在多繼承下:
1.子類(lèi)中每一個(gè)繼承的父類(lèi)都有自己的虛表,存放父類(lèi)中的虛函數(shù);
2.子類(lèi)中重寫(xiě)的虛函數(shù)會(huì)覆蓋子類(lèi)中父類(lèi)虛表對(duì)應(yīng)的虛函數(shù),Base1和Base2中的func1都沒(méi)覆蓋為了Derive::func1;
3.子類(lèi)中繼承的Base1中的func1和Base2中的func1的地址不同,但它們都是Derive重寫(xiě)后的虛函數(shù),最終調(diào)用的是同一個(gè)func1,只是中間多了一個(gè)步驟;
4.子類(lèi)未重寫(xiě)的的虛函數(shù)放在第一個(gè)繼承的父類(lèi)的虛表中;
以下程序的輸出結(jié)果是:
B和C都是虛繼承A,D多繼承B和C,所以B和C在D中共享一個(gè)A,所以B和C都不能去初始化D中的A對(duì)象,只能在D中單獨(dú)進(jìn)行A的初始化;
初始化是按照類(lèi)聲明的順序來(lái)的,不是按照初始化列表的順序,所以在D中先初始化A對(duì)象,在初始化B和C,這事就不會(huì)重復(fù)初始化A了,最后初始化D,所以答案選A。
可以,inline函數(shù)是沒(méi)有地址的,而且inline只是對(duì)編譯器的一個(gè)建議,當(dāng)一個(gè)inline函數(shù)是虛函數(shù)時(shí),在多態(tài)調(diào)用以后,inline就失效了,因?yàn)樘摵瘮?shù)要放進(jìn)虛表中。
3.靜態(tài)成員函數(shù)可以是虛函數(shù)嗎不可以,static函數(shù)沒(méi)有this指針,可以直接使用類(lèi)名::函數(shù)名()的方式調(diào)用,而使用類(lèi)名::函數(shù)名()的方式無(wú)法訪問(wèn)對(duì)象的虛表,因此靜態(tài)成員函數(shù)無(wú)法放進(jìn)虛表,虛函數(shù)是為了實(shí)現(xiàn)多態(tài),多態(tài)運(yùn)行時(shí)都是去虛表中找決議,靜態(tài)成員函數(shù)都是在編譯時(shí)就決議了,因此它是虛函數(shù)沒(méi)有價(jià)值。
4.構(gòu)造函數(shù)可以是虛函數(shù)嗎不可以,因?yàn)樘摵瘮?shù)是為了實(shí)現(xiàn)多態(tài)調(diào)用,運(yùn)行時(shí)去虛表中找對(duì)應(yīng)的虛函數(shù)進(jìn)行調(diào)用,對(duì)象中的虛表指針都是在構(gòu)造函數(shù)初始化列表階段才初始化的,構(gòu)造函數(shù)是虛函數(shù)沒(méi)有意義。
5.析構(gòu)函數(shù)可以是虛函數(shù)嗎可以,并且最好把基類(lèi)的析構(gòu)函數(shù)定義為虛函數(shù),詳情參考 二-5-3。
6.拷貝構(gòu)造和賦值可以是虛函數(shù)嗎拷貝構(gòu)造不可以,因?yàn)榭截悩?gòu)造也是構(gòu)造函數(shù),參考上面的構(gòu)造函數(shù);
賦值重載operator==()可以,但是沒(méi)有實(shí)際價(jià)值。
如果虛函數(shù)不構(gòu)成多態(tài),是一樣快的;
如果虛函數(shù)構(gòu)成多態(tài),調(diào)用普通函數(shù)比較快,因?yàn)闃?gòu)成多態(tài)調(diào)用虛函數(shù)時(shí),運(yùn)行中需要到虛表中去查找。
虛函數(shù)表是在編譯階段就生成好的,存在代碼段(常量區(qū));
構(gòu)造函數(shù)初始化列表階段初始化的是虛函數(shù)表指針,對(duì)象中存的也是虛函數(shù)表指針。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
當(dāng)前名稱:C++知識(shí)點(diǎn)--多態(tài)-創(chuàng)新互聯(lián)
鏈接地址:http://aaarwkj.com/article10/ddoego.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、虛擬主機(jī)、關(guān)鍵詞優(yōu)化、軟件開(kāi)發(fā)、外貿(mào)網(wǎng)站建設(shè)、品牌網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容