欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++數(shù)據(jù)結(jié)構(gòu)分析多態(tài)的實現(xiàn)與原理及抽象類

 更新時間:2022年02月28日 15:40:32   作者:呆呆獸學(xué)編程  
繼承就是可以直接使用前輩的屬性和方法。自然界如果沒有繼承,那一切都是處于混沌狀態(tài)。多態(tài)是同一個行為具有多個不同表現(xiàn)形式或形態(tài)的能力。多態(tài)就是同一個接口,使用不同的實例而執(zhí)行不同操作

??上一篇博客我和大家聊了聊關(guān)于繼承的內(nèi)容,繼承是C++的三大特性之一,今天要和大家聊一聊有關(guān)C++的三大特性中的最后一個——多態(tài)。 ??博客代碼已上傳至gitee:https://gitee.com/byte-binxin/cpp-class-code

??多態(tài)的

??概念

多態(tài): 從字面意思來看,就是事物的多種形態(tài)。用C++的語言說就是不同的對象去完成同一個行為會產(chǎn)生不同的效果。

??虛函數(shù)

虛函數(shù): 被virtual關(guān)鍵字修飾的類成員函數(shù)叫做虛函數(shù)。

實例演示: 看一下代碼,其中BuyTicket成員函數(shù)被virtual關(guān)鍵字修飾

class Person
{
public:
	// 虛函數(shù)
	virtual void BuyTicket()
	{
		cout << "買票全價" << endl;
	}
};

??多態(tài)構(gòu)成的條件

多態(tài)是在不同繼承關(guān)系的類對象,去調(diào)用同一函數(shù),產(chǎn)生了不同的行為。

繼承中構(gòu)成多態(tài)有兩個條件:

  • 必須有基類的指針或引用調(diào)用
  • 被調(diào)用的函數(shù)必須是虛函數(shù),其派生類必須對基類的虛函數(shù)進(jìn)行重寫

虛函數(shù)的重寫是什么?

虛函數(shù)的重寫(覆蓋): 派生類中有一個跟基類完全相同的虛函數(shù)(即派生類虛函數(shù)與基類虛函數(shù)的返回值類型、函數(shù)名字、參數(shù)列表完全相同),稱子類的虛函數(shù)重寫了基類的虛函數(shù)。(重寫是對函數(shù)體進(jìn)行重寫)

實例演示:

class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "買票全價" << endl;
	}
};

class Student : public Person
{
public:
	virtual void BuyTicket() // 這里也可以不寫virtual,因為基類的虛函數(shù)屬性已經(jīng)被保留下來了,這里只是完成虛函數(shù)的重寫
	{
		cout << "買票半價" << endl;
	}
};

虛函數(shù)重寫的兩個例外:

1.協(xié)變:基類和派生類的虛函數(shù)的返回類型不同

派生類重寫基類虛函數(shù)時,與基類虛函數(shù)返回值類型不同。即基類虛函數(shù)返回基類對象的指針或者引用,派生類虛函數(shù)返回派生類對象的指針或者引用時,稱為協(xié)變。(也就是基類虛函數(shù)的返回類型和派生類的虛函數(shù)的返回類型是父子類型的指針或引用)

// 協(xié)變  返回值類型不同,但它們之間是父子或父父關(guān)系  返回類型是指針或者引用
// 基類虛函數(shù)   返回類型  是  基類的指針或者引用  
// 派生類虛函數(shù) 返回類型  是  基類或派生類的返回類型是基類的指針或引用

class A {};
class B : public A {};
class Person {
public:
	virtual A* f() { return new A; }
};
class Student : public Person {
public:
	virtual A* f() { return new B; }
};

2.析構(gòu)函數(shù)的重寫 基類與派生類的析構(gòu)函數(shù)的函數(shù)名不同
我在上一篇博客中說到過,基類和派生類的析構(gòu)函數(shù)的函數(shù)名會被編譯器統(tǒng)一處理成destructor,所以只要基類的析構(gòu)函數(shù)加了關(guān)鍵字virtual,就會和派生類的析構(gòu)函數(shù)構(gòu)成重寫。

我們再回到多態(tài)構(gòu)成的兩個條件中,完成基類虛函數(shù)的重寫我已經(jīng)介紹了,還有一個必須由基類的指針或引用調(diào)用的條件,這個應(yīng)該很好理解吧。下面舉個例子: 實例演示:

class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "買票全價" << endl;
	}
};

class Student : public Person
{
public:
	virtual void BuyTicket() // 這里也可以不寫virtual,因為基類的虛函數(shù)屬性已經(jīng)被保留下來了,這里只是完成虛函數(shù)的重寫
	{
		cout << "買票半價" << endl;
	}
};

void Func1(Person& p) { p.BuyTicket(); }
void Func2(Person* p) { p->BuyTicket(); }
void Func3(Person p) { p.BuyTicket(); }

int main()
{
	Person p;
	Student s;

	// 滿足多態(tài)的條件:與類型無關(guān),父類指針指向的是誰就調(diào)用誰的成員函數(shù)
	// 不滿足多態(tài)的條件:與類型有關(guān),類型是誰就調(diào)用誰的成員函數(shù)
	cout << "基類的引用調(diào)用:" << endl;
	Func1(p);
	Func1(s);

	cout << "基類的指針調(diào)用:" << endl;
	Func2(&p);
	Func2(&s);

	cout << "基類的對象調(diào)用:" << endl;
	Func3(p);
	Func3(s);

	return 0;
}

代碼運行結(jié)果:

總結(jié):

  • 滿足多態(tài)的條件:成員函數(shù)調(diào)用與對象類型無關(guān),指向那個對象就調(diào)用哪個的虛函數(shù)
  • 不滿足多態(tài)的條件:成員函數(shù)的調(diào)用與對象類型有關(guān),是哪個對象類型就調(diào)用哪個對象的虛函數(shù)。

思考: 析構(gòu)函數(shù)是否要加virtual? 答案是需要的。先給大家看一個例子:

class Person
{
public:
	/*virtual*/ ~Person()
	{
		cout << "~Person()" << endl;
	}
};
class Student: public Person
{
public:
	~Student()
	{
		cout << "~Student()" << endl;
	}
};
int main()
{
	Person* p = new Person;
	Person* ps = new Student;// 不加virtual,不構(gòu)成多態(tài),父類指針只會根據(jù)類型去調(diào)用對于的析構(gòu)函數(shù)
	// 加了virtual,構(gòu)成多態(tài),父類指針會根據(jù)指向的對象去調(diào)用他的析構(gòu)函數(shù)

	delete p;
	delete ps;

	return 0;
}

下面分別是基類析構(gòu)函數(shù)不加virtual和加virtual的代碼運行結(jié)果:

可以看出,不加virtual關(guān)鍵字時,第二個對象delete時沒有調(diào)用子類的析構(gòu)函數(shù)清理釋放空間。為什么呢?因為不加virtual關(guān)鍵字時,兩個析構(gòu)函數(shù)不構(gòu)成多態(tài),所以調(diào)用析構(gòu)函數(shù)時是與類型有關(guān)的,因為都是都是父類類型,所以只會調(diào)用父類的析構(gòu)函數(shù)。加了virtual關(guān)鍵字時,因為兩個析構(gòu)函數(shù)被編譯器處理成同名函數(shù)了,所以完成了虛函數(shù)的重寫,且是父類指針調(diào)用,所以此時兩個析構(gòu)函數(shù)構(gòu)成多態(tài),所以調(diào)用析構(gòu)函數(shù)時是與類型無關(guān)的,因為父類指針指向的是子類對象,所以會調(diào)用子類的析構(gòu)函數(shù),子類調(diào)用完自己的析構(gòu)函數(shù)又會自動調(diào)用父類的析構(gòu)函數(shù)來完成對父類資源的清理。 所以總的來看,基類的析構(gòu)函數(shù)是要加virtual的。

??C++11override和final

final: 修飾虛函數(shù),表示該虛函數(shù)不可以被重寫(還可以修飾類,表示該類不可以被繼承)

實例演示:

class Car
{
public:
	// final  表示該虛函數(shù)不能被重寫  也可以修飾類,表示該類不可以被繼承
	virtual void Drive() final {}
};
class Benz :public Car
{
public:
	virtual void Drive() { cout << "Benz-舒適" << endl; }
};

編譯器檢查結(jié)果: 由于dirve字母編寫錯誤,所以編譯器檢查出沒有重寫基類的虛函數(shù)

2.overide: 檢查派生類虛函數(shù)是否重寫了基類的某個虛函數(shù) 實例演示:

class Car
{
public:
	// final  表示該虛函數(shù)不能被重寫  也可以修飾類,表示該類不可以被繼承
	virtual void Drive() final {}
};
class Benz :public Car
{
public:
	virtual void Drive() { cout << "Benz-舒適" << endl; }
};

編譯器檢查結(jié)果:

??重載、重寫和重定義(隱藏)

名稱 作用域 函數(shù)名 其他
重載 兩個函數(shù)在同一作用域 相同 參數(shù)類型不同
重寫 兩個函數(shù)分別再基類和派生類的作用域 相同 函數(shù)返回類型和參數(shù)類型一樣
重定義(隱藏) 兩個函數(shù)分別再基類和派生類的作用域 相同 兩個基類和派生類的同名函數(shù)不是構(gòu)成重寫就是重定義

??抽象類

概念: 在虛函數(shù)的后面寫上 =0 ,則這個函數(shù)為純虛函數(shù)。包含純虛函數(shù)的類叫做抽象類(也叫接口類),抽象類不能實例化出對象。派生類繼承后也不能實例化出對象,只有重寫純虛函數(shù),派生類才能實例化象純虛函數(shù)規(guī)范了派生類必須重寫,另外純虛函數(shù)更體現(xiàn)出了接口繼承。

總結(jié)出幾個特點:

  • 虛函數(shù)后面加上=0
  • 不能實例化出對象
  • 派生類如果不重寫基類的純虛函數(shù)那么它也是抽象類,不能實例化出對象
  • 抽象類嚴(yán)格限制派生類必須重寫基類的純虛函數(shù)
  • 體現(xiàn)了接口繼承

實例演示:

class Car
{
public:
	virtual void Drive() = 0;
};
class Benz : public Car
{
public:
	virtual void Drive()
	{
		cout << "Benz" << endl;
	}
};


class BMW : public Car
{
public:
	virtual void Drive () override
	{
		cout << "BMW" << endl;
	}
};

int main()
{
	Car* pBenZ = new Benz;
	pBenZ->Drive();

	Car* pBMW = new BMW;
	pBMW->Drive();

	delete pBenZ;
	delete pBMW;
	return 0;
}

代碼運行結(jié)果:

抽象類的意義?

  • 強制子類完成父類虛函數(shù)的重寫
  • 表示該類是抽象類,沒有實體(例如:花、車和人等)

接口繼承和實現(xiàn)繼承

普通函數(shù)的繼承是一種實現(xiàn)繼承,派生類繼承了基類函數(shù),可以使用函數(shù),繼承的是函數(shù)的實現(xiàn)。虛函數(shù)的繼承是一種接口繼承,派生類繼承的是基類虛函數(shù)的接口,目的是為了重寫,達(dá)成多態(tài),繼承的是接口。所以如果不實現(xiàn)多態(tài),不要把函數(shù)定義成虛函數(shù)。

??多態(tài)的原理

??虛函數(shù)表

概念: 一個含有虛函數(shù)的類中至少有一個虛函數(shù)指針,這個指針指向了一張表——虛函數(shù)表(簡稱虛表),這張表中存放了這個類中所有的虛函數(shù)的地址。

計算一下下面這個類的大小:

class Base
{
public:
	virtual void func1() {}
	virtual void func2() {}
public:
	int _a;
};
int main()
{
	cout << sizeof(Base) << endl;
	return 0;
}

代碼運行結(jié)果如下:

這個類中存放了一個虛表指針和一個成員變量,所以總大小就是8。給大家看一下它的類對象模型:

實例演示:

class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "買票全價" << endl;
	}
	virtual void func()
	{
		cout << "func()" << endl;
	}
	int _p = 1;
};

class Student : public Person
{
public:
	virtual void BuyTicket() // 這里也可以不寫virtual,因為基類的虛函數(shù)屬性已經(jīng)被保留下來了,這里只是完成虛函數(shù)的重寫
	{
		cout << "買票半價" << endl;
	}
	int _s = 1;
};

int main()
{
	Person p;
	Student s;

	return 0;
}

類對象模型如下:

可以看出,兩個虛函數(shù)地址是不一樣的,其實子類會先把父類的虛表拷貝一份下來,如果子類重寫了虛函數(shù),那么子類的虛函數(shù)的地址將會覆蓋虛表中的地址,如果沒有重寫,那么將不覆蓋。

總結(jié)幾點:

  • 子類對象由兩部分構(gòu)成,一部分是父類繼承下來的成員,虛表指針指向的虛表有父類的虛函數(shù),也有子類新增的虛函數(shù)
  • 子類完成父類虛函數(shù)的重寫其實是對繼承下來的虛表的中重寫了的虛函數(shù)進(jìn)行覆蓋,把地址更換了,語法層是稱為覆蓋
  • 虛函數(shù)表本質(zhì)是一個存虛函數(shù)指針的指針數(shù)組,一般情況這個數(shù)組最后面放了一個nullptr
  • 虛表生成的過程:先將基類中的虛表內(nèi)容拷貝一份到派生類虛表中 b.如果派生類重寫了基類中某個虛函數(shù),用派生類自己的虛函數(shù)覆蓋虛表中基類的虛函數(shù) c.派生類自己新增加的虛函數(shù)按其在派生類中的聲明次序增加到派生類虛表的最后

下面我們來討論一下虛表存放的位置和虛表指針存放的位置

虛表指針肯定是存在類中的,從上面的類對象模型中可以看出。其次虛表存放的是虛函數(shù)的地址,這些虛函數(shù)和普通函數(shù)一樣,都會被編譯器編譯成指令,然后放進(jìn)代碼段。虛表也是存在代碼段的,因為同類型的對象共用一張?zhí)摫?。下面帶大家驗證一下(環(huán)境:vs2019)

驗證代碼:

class Base
{
public:
	virtual void func1() { cout << "Base::func1" << endl; }
	virtual void func2() { cout << "Base::func2" << endl; }
	virtual void func3() { cout << "Base::func3" << endl; }
	void func() {}

	int b = 0;
};

class Derive :public Base
{
public:
	virtual void func1() { cout << "Derive::func1" << endl; }
	virtual void func2() { cout << "Derive::func2" << endl; }
	virtual void func4() { cout << "Derive::func4" << endl; }
	virtual void func5() { cout << "Derive::func5" << endl; }

	int d = 0;
};

void func() {}
int globalVar = 10;
int main()
{
	Base b;
	Derive d;
	const char* pChar = "hello";
	int c = 1;
	static int s = 20;
	int* p = new int;
	const int i = 10;

	printf("棧變量:%p\n", &c);
	printf("虛表指針:%p\n", (int*)&b);
	printf("對象成員:%p\n", ((int*)&b + 1));
	printf("堆變量:%p\n", p);
	printf("代碼段常量:%p\n", pChar);
	printf("普通函數(shù)地址:%p\n", func);
	printf("成員函數(shù)地址:%p\n", &Base::func);
	printf("虛函數(shù):%p\n", &Base::func1);
	printf("虛函數(shù)表:%p\n", *(int*)&b);
	printf("數(shù)據(jù)段:%p\n", &s);
	printf("數(shù)據(jù)段:%p\n", &globalVar);

	delete p;
	return 0;
}

代碼運行結(jié)果如下:

容易看出,代碼段常量存放的地址和虛表存放的地址很接近,和數(shù)據(jù)段的地址也很接近,所以可以猜測虛表存放在數(shù)據(jù)段或代碼段,更可能是在代碼段。

??原理

多態(tài)是在運行時到指向的對象中的虛表中查找要調(diào)用的虛函數(shù)的地址,然后進(jìn)行調(diào)用。

總結(jié):

  • 多態(tài)滿足的兩個條件:一個是虛函數(shù)的覆蓋,一個是對象的指針和引用調(diào)用
  • 滿足多態(tài)后,函數(shù)的調(diào)用不是編譯時確認(rèn)的,而是在運行時確認(rèn)的。

動態(tài)綁定和靜態(tài)綁定

  • 靜態(tài)綁定: 發(fā)生在編譯時,也就是早期綁定,就是我們之前說過的函數(shù)重載就是屬于靜態(tài)綁定,也稱靜態(tài)多態(tài)。
  • 動圖綁定: 發(fā)生在運行時,也就是后期綁定,多態(tài)就是發(fā)生在運行時,也稱動態(tài)多態(tài)。

??單繼承和多繼承的虛表

??單繼承的虛表

先看下面的代碼(單繼承)

class Base
{
public:
	virtual void func1() { cout << "Base::func1" << endl; }
	virtual void func2() { cout << "Base::func2" << endl; }
	virtual void func3() { cout << "Base::func3" << endl; }
	void func() {}

	int b = 0;
};

class Derive :public Base
{
public:
	virtual void func1() { cout << "Derive::func1" << endl; }
	virtual void func2() { cout << "Derive::func2" << endl; }
	virtual void func4() { cout << "Derive::func4" << endl; }
	virtual void func5() { cout << "Derive::func5" << endl; }

	int d = 0;
};

觀察它的類對象模型:

在上面的類對象模型中,派生類中只可以看見func1和func2,后面兩個函數(shù)看不見,這是因為編譯器把這兩個新增的虛函數(shù)給隱藏了,為了我們能夠更好的觀察,我們可以通過寫代碼來看。 先定義一個函數(shù)指針:

typedef void(*VF_PTR)(); // 給函數(shù)指針typedef

下面是打印虛表的代碼:

void PrintVFTable(VF_PTR* pTable)
{
	for (size_t i = 0; pTable[i] != nullptr; ++i)
	{
		printf("vfTable[%d]:%p->", i, pTable[i]);
		VF_PTR f = pTable[i];
		f();// 通過函數(shù)地址調(diào)用函數(shù)
	}

	cout << endl;
}

下面我們只需要通過傳虛表地址的方式來調(diào)用函數(shù)打印虛表,虛表地址如何獲取呢?從上面的類對象模型可以知道,類對象的前四個地址存放的是虛表指針,虛表指針也就是虛表的指針,所以我們要獲取類對象的前四個字節(jié)。下面是獲取方法:

(VF_PTR*)*(int*)&b;

先將類對象的地址取出,然后強轉(zhuǎn)為整形,解引用就會按照四個字節(jié)來獲取內(nèi)容,這四個字節(jié)的內(nèi)容是虛表指針,其實也是虛表的地址,我們可以把這個整形強轉(zhuǎn)為函數(shù)地址的類型就可以了。

打印虛表:

int main()
{
	Base b;
	Derive d;

	PrintVFTable((VF_PTR*)*(int*)&b);
	PrintVFTable((VF_PTR*)*(int*)&d);

	return 0;
}

打印結(jié)果如下:

可以看出派生類對象中新增的虛函數(shù)會按照虛函數(shù)函數(shù)次序聲明放在虛表的最后。

??多繼承的虛函數(shù)表

看下面代碼(多繼承)

class Base1 
{
public:
	virtual void func1() { cout << "Base1::func1" << endl; }
	virtual void func2() { cout << "Base1::func2" << endl; }
private:
	int b1;
};
class Base2 
{
public:
	virtual void func1() { cout << "Base2::func1" << endl; }
	virtual void func2() { cout << "Base2::func2" << endl; }
private:
	int b2 = 1;
};
class Derive : public Base1 , public Base2 
{
public:
	virtual void func1() { cout << "Derive::func1" << endl; }
	virtual void func3() { cout << "Derive::func3" << endl; }
private:
	int d1 = 1;
};

類對象模型如下:

為了更好地觀察,我們還是通過打印虛表來觀察:

int main()
{
	Derive d;
	cout << sizeof(Derive) << endl;
	cout << "Base1的虛表:" << endl;
	PrintVFTable((VF_PTR*)*(int*)&d);

	cout << "Base2的虛表:" << endl;
	PrintVFTable((VF_PTR*)*(int*)((char*)&d+sizeof(Base1)));

	cout << "Derive的成員變量d:" << endl;
	//PrintVFTable((VF_PTR*)*(int*)((char*)&d + sizeof(Base1) + sizeof(Base2)));
	cout << *(int*)((char*)&d + sizeof(Base1) + sizeof(Base2)) << endl;
	return 0;
}

打印結(jié)果如下:

可以看出,派生類新增的虛函數(shù)放在了第一個繼承的對象的虛表中最后了。

??幾個值得思考的問題

  • 內(nèi)斂函數(shù)可以是虛函數(shù)嗎?

答:不可以,內(nèi)聯(lián)(inline)函數(shù)沒有地址,因為虛函數(shù)要把地址放到虛表中去。

  • 構(gòu)造函數(shù)可以是虛函數(shù)嗎?

答:不可以,因為對象中虛函數(shù)指針是在構(gòu)造函數(shù)初始化列表階段才初始化的。

  • 析構(gòu)函數(shù)可以是虛函數(shù)嗎?

答:可以,且建議設(shè)計成虛函數(shù),具體原因前面說了。

  • 對象訪問普通函數(shù)快還是虛函數(shù)更快?

答:首先如果是普通對象,是一樣快的。如果是指針對象或者是引用對象,則調(diào)用的普通函數(shù)快,因為構(gòu)成多態(tài),運行時調(diào)用虛函數(shù)需要到虛函數(shù)表中去查找。

  • 虛函數(shù)表是在什么階段生成的?

答:在編譯階段生成的,存在于代碼段。

  • 什么是抽象類?有什么意義?

答:前面介紹過了,可以參考前文。

??總結(jié)

多態(tài)也是C++的三大特性之一,之前也介紹過兩個,就是封裝和繼承。多態(tài)也是十分的重要,我們要理清其中一些改了,更好地理解這些。今天的內(nèi)容就到這里了,喜歡的話,歡迎點贊支持和關(guān)注~

到此這篇關(guān)于C++數(shù)據(jù)結(jié)構(gòu)分析多態(tài)的實現(xiàn)與原理及抽象類的文章就介紹到這了,更多相關(guān)C++ 多態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Qt制作一個定時關(guān)機的小程序

    基于Qt制作一個定時關(guān)機的小程序

    這篇文章主要為大家詳細(xì)介紹了如何基于Qt制作一個有趣的定時關(guān)機的小程序,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • 詳解C語言中index()函數(shù)和rindex()函數(shù)的用法

    詳解C語言中index()函數(shù)和rindex()函數(shù)的用法

    這篇文章主要介紹了C語言中index()函數(shù)和rndex()函數(shù)的用法,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,要的朋友可以參考下
    2015-08-08
  • vscode和cmake編譯多個C++文件的實現(xiàn)方法

    vscode和cmake編譯多個C++文件的實現(xiàn)方法

    這篇文章主要介紹了vscode和cmake編譯多個C++文件的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 使用c++實現(xiàn)OpenCV圖像橫向&縱向拼接

    使用c++實現(xiàn)OpenCV圖像橫向&縱向拼接

    這篇文章主要介紹了使用c++實現(xiàn)OpenCV圖像橫向&縱向拼接,文中有圖像拼接函數(shù),可以實現(xiàn)如“長圖拼接王”這類小程序的類似功能,大家可以將該函數(shù)封裝在軟件中自由使用
    2021-08-08
  • C++中的對象初始化操作代碼

    C++中的對象初始化操作代碼

    對象初始化可以分為默認(rèn)初始化、直接初始化、拷貝初始化以及值初始化。本文重點給大家介紹C++中的對象初始化操作代碼,感興趣的朋友跟隨小編一起看看吧
    2021-12-12
  • C++實現(xiàn)圖書信息管理系統(tǒng)

    C++實現(xiàn)圖書信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實現(xiàn)圖書信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++中可正確獲取UTF-8字符長度的函數(shù)分享

    C++中可正確獲取UTF-8字符長度的函數(shù)分享

    這篇文章主要介紹了C++中可正確獲取UTF-8字符長度的函數(shù)分享,需要的朋友可以參考下
    2014-08-08
  • C/C++中字符串流詳解及其作用介紹

    C/C++中字符串流詳解及其作用介紹

    這篇文章主要介紹了C/C++中字符串流詳解及其作用,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • 最新評論