泛型(Generic Programming)即是指具有在多種數(shù)據(jù)類型上皆可操作的含意。 泛型編程的代表作品STL是一種高效、泛型、可交互操作的軟件組件。
泛型編程最初誕生于C++中,目的是為了實現(xiàn)C++的STL(標(biāo)準(zhǔn)模板庫)。其語言支持機制就是模板(Templates)。模板的核心思想是參數(shù)化類型,即把一個原本特定于某個類型的算法或類當(dāng)中的類型信息抽掉,抽出來做成模板參數(shù)T。
定義一個交換兩個數(shù)的宏
#define SWAP(t, a, b) \
do \
{ \
t c = a; \
a = b; \
b = c; \
}while(0);
宏代碼塊實現(xiàn)的優(yōu)點是代碼復(fù)用,適合所有類型;缺點是缺少類型檢查。
#include <iostream>
using namespace std;
void swap(int &a, int& b)
{
int t = a;
a = b;
b = t;
}
void swap(double &a,double b)
{
double t = a;
a = b;
b = t;
}
int main()
{
int ia = 10; int ib = 20;
swap(ia,ib);
cout<<ia<<ib<<endl;
double da = 10, db = 20;
swap(da,db);
cout<<da<<db<<endl;
return 0;
}
函數(shù)重載實現(xiàn)的優(yōu)點是真正進行函數(shù)調(diào)用,C++編譯器進行類型檢查;缺點是根據(jù)類型重復(fù)定義函數(shù),無法代碼復(fù)用。
函數(shù)模板是可用不同類型進行調(diào)用的特殊函數(shù),關(guān)鍵在于類型參數(shù)化。
函數(shù)模板的語法格式如下:
template<typename/class 類型參數(shù)表>
返回類型 函數(shù)模板名(函數(shù)參數(shù)列表)
{
函數(shù)模板定義體
}
template關(guān)鍵字用于聲明開始進行泛型編程。
typename關(guān)鍵字用于聲明泛指類型。
函數(shù)模板可以自動推導(dǎo)類型進行調(diào)用,也可以顯示指定具體類型進行調(diào)用。
#include <iostream>
using namespace std;
template <typename T>
void Swap(T& a,T &b )
{
T t = a;
a = b;
b = t;
}
int main()
{
int ia = 10; int ib = 20;
Swap(ia,ib); //Swap<int>(ia,ib);
cout<<ia<<ib<<endl;
double da = 10, db = 20;
Swap(da,db); //Swap<double>(da,db);
cout<<da<<db<<endl;
string sa ="china"; string sb = "America";
Swap(sa,sb);
cout<<sa<<sb<<endl;
return 0;
}
判斷一個變量是不是指針類型示例:
template
<typename T>
bool isPtr(T *p)
{
return true;
}
template
<typename T>
bool isPtr(T t)
{
return false;
}
函數(shù)模板,只適用于函數(shù)的參數(shù)個數(shù)相同而類型不同,且函數(shù)體相同的情況。如果個數(shù)不同,則不能用函數(shù)模板。
C++編譯器從函數(shù)模板通過具體類型產(chǎn)生不同的函數(shù),C++編譯器會對函數(shù)模板進行兩次編譯,一次是函數(shù)模板代碼進行編譯,一次是參數(shù)替換后的函數(shù)代碼進行編譯。
#include <iostream>
using namespace std;
template <typename T>
void Swap(T& a, T& b)
{
T c = a;
a = b;
b = c;
}
class Test
{
};
typedef void (*pFuncInt)(int&, int&);
typedef void (*pFuncDouble)(double&, double&);
typedef void (*pFuncTest)(Test&, Test&);
int main(int argc, char *argv[])
{
pFuncInt pi = Swap;//Swap<int>
printf("0x%x\n", pi);
pFuncDouble pd = Swap;//Swap<double>
printf("0x%x\n", pd);
pFuncTest pt = Swap;//Swap<Test>
printf("0x%x\n", pt);
return 0;
}
函數(shù)模板本身不允許隱式類型轉(zhuǎn)換,因此,自動推導(dǎo)類型時需要嚴(yán)格匹配,但當(dāng)顯示指定類型參數(shù)時可以進行隱式類型轉(zhuǎn)換。
函數(shù)模板中的返回值類型必須顯示指定。
add<int>(ia,ib);
函數(shù)模板可以定義多個不同的類型參數(shù),但無法自動推導(dǎo)返回值類型,可以從左向右部分指定類型參數(shù),實際工程中將返回值作為第一個類型參數(shù),必須顯式指定。
#include <iostream>
#include <string>
using namespace std;
template
< typename T1, typename T2, typename T3 >
T1 Add(T2 a, T3 b)
{
return static_cast<T1>(a + b);
}
int main()
{
// T1 = int, T2 = double, T3 = double
int r1 = Add<int>(0.5, 0.8);
// T1 = double, T2 = float, T3 = double
double r2 = Add<double, float>(0.5, 0.8);
// T1 = float, T2 = float, T3 = float
float r3 = Add<float, float, float>(0.5, 0.8);
cout << "r1 = " << r1 << endl; // r1 = 1
cout << "r2 = " << r2 << endl; // r2 = 1.3
cout << "r3 = " << r3 << endl; // r3 = 1.3
return 0;
}
函數(shù)模板可以被重載,C++編譯器優(yōu)先考慮普通函數(shù),但如果函數(shù)模板可以產(chǎn)生更好的匹配,則使用函數(shù)模板,可以通過空模板實參列表限定只能使用函數(shù)模板。
#include <iostream>
#include <string>
using namespace std;
template < typename T >
T Max(T a, T b)
{
cout << "T Max(T a, T b)" << endl;
return a > b ? a : b;
}
int Max(int a, int b)
{
cout << "int Max(int a, int b)" << endl;
return a > b ? a : b;
}
template < typename T >
T Max(T a, T b, T c)
{
cout << "T Max(T a, T b, T c)" << endl;
return Max(Max(a, b), c);
}
int main()
{
int a = 1;
int b = 2;
cout << Max(a, b) << endl; // 普通函數(shù) Max(int, int)
cout << Max<>(a, b) << endl; // 函數(shù)模板 Max<int>(int, int)
cout << Max(3.0, 4.0) << endl; // 函數(shù)模板 Max<double>(double, double)
cout << Max(5.0, 6.0, 7.0) << endl; // 函數(shù)模板 Max<double>(double, double, double)
cout << Max('a', 100) << endl; // 普通函數(shù) Max(int, int)
return 0;
}
C++語言中將模板的思想應(yīng)用于類,使得類的實現(xiàn)不關(guān)注數(shù)據(jù)元素的具體類型,只關(guān)注類需要實現(xiàn)的功能。
類模板的定義語法如下:
template <typename T>
class classname
{
};
在類聲明前使用template進行標(biāo)識,<typename T>
用于說明類中使用泛指類型T。
類內(nèi)定義成員函數(shù)
template<typename T>
class classname
{
public:
void push(int size)
{
}
}
類外定義函數(shù)
template<typename T>
void classname<T>::push(T data)
{
}
類模板實例化為模板類:
classname<double> object;
類模板是類的抽象,類是類模板的實例。
類模板只能顯示指定類型參數(shù),無法自動推導(dǎo)。聲明的泛型類型參數(shù)可以出現(xiàn)在類模板的任意地方。
類模板必須在頭文件中實現(xiàn),不能分開實現(xiàn)在不同文件中。類模板的成員函數(shù)需要定義在外部定義時,每個成員函數(shù)需要加上類模板template<typename T>
聲明。
類模板適合以相同的邏輯處理不同的數(shù)據(jù)類型的數(shù)據(jù),因此非常適合編寫數(shù)據(jù)結(jié)構(gòu)相關(guān)代碼。
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
using namespace std;
template<typename T>
class Stack
{
public:
Stack(int size)
{
space = new T[size];
top = 0;
}
~Stack();
bool isEmpty();
bool isFull();
void push(T data);
T pop();
private:
T* space;
int top;
};
template<typename T>
Stack<T>::~Stack()
{
delete []space;
}
template<typename T>
bool Stack<T>::isEmpty()
{
return top == 0;
}
template<typename T>
bool Stack<T>::isFull()
{
return top == 1024;
}
template<typename T>
void Stack<T>::push(T data)
{
space[top++] = data;
}
template<typename T>
T Stack<T>::pop()
{
return space[--top];
}
int main()
{
Stack<double> s(100); //Stack<string> s(100);
if(!s.isFull())
s.push(10.3);
if(!s.isFull())
s.push(20);
if(!s.isFull())
s.push(30);
if(!s.isFull())
s.push(40);
if(!s.isFull())
s.push(50);
while(!s.isEmpty())
cout<<s.pop()<<endl;
return 0;
}
類模板通過具體類型產(chǎn)生不同的類,C++編譯器在類模板聲明的地方對類模板代碼本身進行編譯,在使用的地方對類模板參數(shù)替換后產(chǎn)生的代碼進行編譯。
類模板可以定義多個不同類型參數(shù)。
#include <iostream>
#include <string>
using namespace std;
template <typename T>
class Operator
{
public:
Operator()
{
cout << "Operator()" << endl;
}
T add(T a, T b)
{
cout << "T add(T a, T b)" << endl;
return a + b;
}
T minus(T a, T b)
{
return a - b;
}
T multiply(T a, T b)
{
return a * b;
}
T divide(T a, T b)
{
return a / b;
}
};
int main(int argc, char *argv[])
{
Operator<int> op1;
cout << op1.add(1, 2) << endl;
cout << op1.add(1, 2) << endl;
Operator<string> op2;
cout << op2.add("D.T.", "Software") << endl;
return 0;
}
// output:
// Operator()
// T add(T a, T b)
// 3
// Operator()
// T add(T a, T b)
// 3
// Operator()
// T add(T a, T b)
// Hello World
上述代碼中,類模板中的函數(shù)代碼在使用的時候才會被分別編譯。
類模板可以被特化,以下情況需要特化類模板:
A、指定特定類型的實現(xiàn)
B、部分參數(shù)類型必須顯示指定
C、根據(jù)類型參數(shù)分開實現(xiàn)類模板
類模板的特化分為部分特化和完全特化。部分特化是指用特定規(guī)則約束類型參數(shù),完全特化是指完全顯示指定類型參數(shù)。
類模板的特化是模板的分開實現(xiàn),本質(zhì)上是同一個類模板,特化類模板必須顯示指定每一個類型參數(shù)。編譯器會自動優(yōu)先選擇特化類模板。
#include <iostream>
using namespace std;
template
<typename T1, typename T2>
class Test
{
public:
void add(T1 a, T2 b)
{
cout << "void add(T1 a, T2 b)" << endl;
cout << a + b << endl;
}
};
//部分特化
template
<typename T>
class Test<T,T>
{
public:
void add(T a, T b)
{
cout << "void add(T a, T b)" << endl;
cout << a + b << endl;
}
void print()
{
cout << "class Test <T,T>" << endl;
}
};
//完全特化
template
<>
class Test<int,int>
{
public:
void add(int a, int b)
{
cout << "void add(int a, int b)" << endl;
cout << a + b << endl;
}
void print()
{
cout << "class Test<int,int>" << endl;
}
};
int main(int argc, char *argv[])
{
Test<int, int> t1;//完全特化
t1.add(1,2);
t1.print();
Test<double, double> t2;//部分特化
t2.add(3.14,2.0);
t2.print();
Test<float, double> t3;//類模板
t3.add(3.14,2.0);
return 0;
}
// output:
// void add(int a, int b)
// 3
// class Test<int,int>
// void add(T a, T b)
// 5.14
// class Test <T,T>
// void add(T1 a, T2 b)
// 5.14
函數(shù)模板只支持模板的完全特化。
#include <iostream>
using namespace std;
//函數(shù)模板
template
<typename T>
bool Equal(T a, T b)
{
cout << "bool Equal(T a, T b)" << endl;
return a == b;
}
//函數(shù)特化模板
template
< >
bool Equal<double>(double a, double b)
{
const double delta = 0.00000000000001;
double r = a - b;
cout << "bool Equal<double>(double a, double b)" << endl;
return (-delta < r) && (r < delta);
}
//函數(shù)重載
bool Equal(double a, double b)
{
const double delta = 0.00000000000001;
double r = a - b;
cout << "bool Equal(double a, double b)" << endl;
return (-delta < r) && (r < delta);
}
int main(int argc, char *argv[])
{
Equal<double>(0.1,0.1);//函數(shù)特化模板
Equal<int>(10,10);//函數(shù)模板
Equal(0.1,0.1);//函數(shù)重載
return 0;
}
// output:
// bool Equal<double>(double a, double b)
// bool Equal(T a, T b)
// bool Equal(double a, double b)
工程實踐中當(dāng)需要重載函數(shù)模板時,優(yōu)先使用函數(shù)模板特化,當(dāng)函數(shù)模板特化無法滿足需求時,使用函數(shù)重載。
模板參數(shù)可以是數(shù)值型參數(shù),數(shù)值型模板參數(shù)存在限制:
A、變量不能作為模板參數(shù)
B、浮點數(shù)不能作為模板參數(shù)
C、類對象不能作為模板參數(shù)
模板參數(shù)是在編譯階段處理的,因此在編譯階段需要唯一確定。
使用最高效方式求1+2+3+4......+100
#include <iostream>
using namespace std;
template
<int N>
class Sum
{
public:
static const int value = Sum<N-1>::value + N;
};
template
<>
class Sum<1>
{
public:
static const int value = 1;
};
int main(int argc, char *argv[])
{
cout<<Sum<100>::value<<endl;
return 0;
}
#ifndef _ARRAY_H_
#define _ARRAY_H_
template
< typename T, int N >
class Array
{
T m_array[N];
public:
int length();
bool set(int index, T value);
bool get(int index, T& value);
T& operator[] (int index);
T operator[] (int index) const;
virtual ~Array();
};
template
< typename T, int N >
int Array<T, N>::length()
{
return N;
}
template
< typename T, int N >
bool Array<T, N>::set(int index, T value)
{
bool ret = (0 <= index) && (index < N);
if( ret )
{
m_array[index] = value;
}
return ret;
}
template
< typename T, int N >
bool Array<T, N>::get(int index, T& value)
{
bool ret = (0 <= index) && (index < N);
if( ret )
{
value = m_array[index];
}
return ret;
}
template
< typename T, int N >
T& Array<T, N>::operator[] (int index)
{
return m_array[index];
}
template
< typename T, int N >
T Array<T, N>::operator[] (int index) const
{
return m_array[index];
}
template
< typename T, int N >
Array<T, N>::~Array()
{
}
#endif
智能指針是C++開發(fā)庫的重要類模板之一,是自動內(nèi)存管理的主要手段,可以避開內(nèi)存的相關(guān)問題。
STL中的智能指針分為auto_ptr、shared_ptr、weak_ptr、unique_ptr四類。
auto_ptr智能指針的特性:
A、生命周期結(jié)束時,銷毀指向的內(nèi)存空間
B、不能指向堆數(shù)組,只能指向堆對象
C、一塊堆空間只能屬于一個智能指針
D、多個智能指針對象不能指向同一塊空間
shared_ptr智能指針的特性:
帶有引用計數(shù)機制,支持多個指針指向同一對象內(nèi)存空間。
weak_ptr智能指針的特性:
weak_ptr是一種弱引用,指向shared_ptr所管理的對象。
unique_ptr智能指針的特性:
一個指針對象指向一片內(nèi)存空間,不能拷貝構(gòu)造和賦值
STL智能指針使用實例:
#include <iostream>
#include <memory>
using namespace std;
class Test
{
string m_name;
public:
Test(const char* name)
{
cout << "Hello, " << name << "." << endl;
m_name = name;
}
void print()
{
cout << "I'm " << m_name << "." << endl;
}
~Test()
{
cout << "Goodbye, " << m_name << "." << endl;
}
};
int main(int argc, char *argv[])
{
auto_ptr<Test> pt(new Test("D.T.Software"));
cout << "pt = " << pt.get() << endl;
pt->print();
cout << endl;
auto_ptr<Test> pt1(pt);
cout << "pt = " << pt.get() << endl;//NULL
cout << "pt1 = " << pt1.get() << endl;//
return 0;
}
QT中的主要智能指針有:QPointer、QSharedPointer、QWeakPointer、QScopedPointer、QSharedDataPoiner、QExplicitlySharedDataPointer。
QPointer智能指針特性:
A、當(dāng)其所指向的對象被銷毀時會被自動置空
B、析構(gòu)時不會自動銷毀所指向的對象
多個QPointer指針對象可以指向同一內(nèi)存空間,當(dāng)所指向?qū)ο蟊讳N毀時指針會被自動置空,但是指針對象析構(gòu)時不會自動銷毀所指向的對象。
QSharedPointer智能指針特性:
A、引用計數(shù)型智能指針
B、可以被自由的拷貝和賦值
C、當(dāng)引用計數(shù)為0時才刪除指向的對象
QT中智能指針使用實例:
#include <QPointer>
#include <QSharedPointer>
#include <QDebug>
class Test : public QObject
{
QString m_name;
public:
Test(const char* name)
{
qDebug() << "Hello, " << name << ".";
m_name = name;
}
void print()
{
qDebug() << "I'm " << m_name << ".";
}
~Test()
{
qDebug() << "Goodbye, " << m_name << ".";
}
};
int main()
{
QPointer<Test> pt(new Test("D.T.Software"));
QPointer<Test> pt1(pt);
QPointer<Test> pt2(pt);//多個QPointer指針對象可以指向同一內(nèi)存空間
pt->print();
pt1->print();
pt2->print();
delete pt;//QPointer智能指針指向的對象被銷毀時,指針對象被置空
qDebug() << "pt = " << pt;//NULL
qDebug() << "pt1 = " << pt1;//NULL
qDebug() << "pt2 = " << pt2;//NULL
qDebug() << endl;
QSharedPointer<Test> spt(new Test("Delphi Tang"));
QSharedPointer<Test> spt1(spt);
QSharedPointer<Test> spt2(spt);
spt->print();
spt1->print();
spt2->print();
return 0;//指針對象都被銷毀時引用計數(shù)為0,自動析構(gòu)指針指向的對象
}
#ifndef _SMARTPOINTER_H_
#define _SMARTPOINTER_H_
template
< typename T >
class SmartPointer
{
T* mp;
public:
SmartPointer(T* p = NULL)
{
mp = p;
}
SmartPointer(const SmartPointer<T>& obj)
{
mp = obj.mp;
const_cast<SmartPointer<T>&>(obj).mp = NULL;
}
SmartPointer<T>& operator = (const SmartPointer<T>& obj)
{
if( this != &obj )
{
delete mp;
mp = obj.mp;
const_cast<SmartPointer<T>&>(obj).mp = NULL;
}
return *this;
}
T* operator -> ()
{
return mp;
}
T& operator * ()
{
return *mp;
}
bool isNull()
{
return (mp == NULL);
}
T* get()
{
return mp;
}
~SmartPointer()
{
delete mp;
}
};
#endif
某些類在整個系統(tǒng)的生命周期中只能有一個對象存在,即單例模式。
要控制類的對象數(shù)目必須隱藏類的構(gòu)造函數(shù),即構(gòu)造函數(shù)聲明為private。
定義一個instance標(biāo)識符,初始化為NULL,當(dāng)需要使用對象時查看instance的值,如果instance為NULL則創(chuàng)建對象并用instance標(biāo)識,如果instance非空則返回instance標(biāo)識的值。
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
template
< typename T >
class Singleton
{
static T* c_instance;
public:
static T* GetInstance();
};
template
< typename T >
T* Singleton<T>::c_instance = NULL;
template
< typename T >
T* Singleton<T>::GetInstance()
{
if( c_instance == NULL )
{
c_instance = new T();
}
return c_instance;
}
#endif
使用代碼:
#include <iostream>
#include <string>
#include "Singleton.h"
using namespace std;
class SObject
{
friend class Singleton<SObject>; // 當(dāng)前類需要使用單例模式
SObject(const SObject&);
SObject& operator= (const SObject&);
SObject()
{
}
public:
void print()
{
cout << "this = " << this << endl;
}
};
int main()
{
SObject* s = Singleton<SObject>::GetInstance();
SObject* s1 = Singleton<SObject>::GetInstance();
SObject* s2 = Singleton<SObject>::GetInstance();
s->print();
s1->print();
s2->print();
return 0;
}
判斷一個變量是不是指針
C++編譯器匹配的調(diào)用優(yōu)先級:
A、重載函數(shù)
B、函數(shù)模板
C、變參函數(shù)
可以根據(jù)C++編譯器匹配的調(diào)用優(yōu)先級,將函數(shù)模板匹配指針變量,返回true,變參函數(shù)匹配非指針變量,返回false。
template
<typename T>
bool IsPtr(T *pt)
{
return true;
}
bool IsPtr(...)
{
return false;
}
但是,由于變參函數(shù)是C語言的內(nèi)容,無法解析C++自定義類型對象,可能造成程序崩潰。
template
<typename T>
char IsPtr(T* v) // match pointer
{
return 'd';
}
int IsPtr(...) // match non-pointer
{
return 0;
}
#define ISPTR(p) (sizeof(IsPtr(p)) == sizeof(char))
上述代碼中,C++編譯器在編譯時會進行函數(shù)匹配,不會進行調(diào)用,避免了參數(shù)為自定義對象時調(diào)用變參函數(shù)導(dǎo)致的程序崩潰。
C++語言在引入了面向?qū)ο缶幊趟枷霑r,使用class關(guān)鍵字定義類類型。C++語言發(fā)展過程中引入了泛型編程,直接復(fù)用class關(guān)鍵字來定義模板。但泛型編程針對的不只是類類型,直接復(fù)用class關(guān)鍵字會使代碼出現(xiàn)二義性。因此,C++直接引入了typename關(guān)鍵字,用于在模板定義中聲明泛指類型,明確告訴C++編譯器聲明的標(biāo)識符為類型。
C++語言中允許類定義中嵌套類型,因此當(dāng)自定義類類型中嵌套類型的標(biāo)識符與其它類類型中定義的成員變量標(biāo)識符重名時將會造成二義性。不同類中的同名標(biāo)識符代表可能導(dǎo)致二義性,因此C++編譯器無法識別標(biāo)識符的確切意義。
#include <iostream>
using namespace std;
class Test1
{
public:
static const int NS = 1;
};
class Test2
{
public:
struct NS
{
int value;
};
};
int a = 0;
template <class T>
void func()
{
T::NS* a;
}
int main(int argc, char *argv[])
{
func<Test1>();
//func<Test2>();//error
//error: dependent-name 'T:: NS' is parsed as a non-type,
//but instantiation yields a type
//say 'typename T:: NS' if a type is meant
return 0;
}
上述代碼中,C++編譯器不會將func函數(shù)模板中NS解析為類型,因此使用Test2作為參數(shù)時,C++編譯器會報錯。因此,為了將NS明確聲明為類型,需要使用typename關(guān)鍵字對NS標(biāo)識符進行聲明。代碼如下:
#include <iostream>
using namespace std;
class Test1
{
public:
static const int NS = 1;
};
class Test2
{
public:
struct NS
{
int value;
};
};
int a = 0;
template <class T>
void func()
{
typename T::NS* a;
}
int main(int argc, char *argv[])
{
//func<Test1>();//error
func<Test2>();
return 0;
}
上述代碼中,NS被明確聲明為類型,因此如果使用Test1作為參數(shù),func函數(shù)模板將會報錯。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
網(wǎng)站標(biāo)題:C++語言學(xué)習(xí)(十七)——模板-創(chuàng)新互聯(lián)
分享網(wǎng)址:http://jinyejixie.com/article46/giheg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗、建站公司、移動網(wǎng)站建設(shè)、網(wǎng)站營銷、自適應(yīng)網(wǎng)站、品牌網(wǎng)站設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)