欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:C++Json項(xiàng)目筆記

柚子快報邀請碼778899分享:C++Json項(xiàng)目筆記

http://yzkb.51969.com/

Github源項(xiàng)目地址:TinyJson

本人倉庫地址(跟原版差別不大,只是在有疑惑或者有收獲的地方加上的注釋作為筆記)

文章目錄

類的提前聲明為什么定義函數(shù)的時候同時寫左值和右值作為傳參?解答

SFINAE機(jī)制(疑惑)指針類型可以被隱式轉(zhuǎn)換成bool類型能夠隱式轉(zhuǎn)換成bool類型的數(shù)據(jù)

為什么要同時有number_value和int_value?(疑惑)什么時候成員函數(shù)需要被聲明為靜態(tài)的?(疑惑)size_t和std::string::size_type還是有區(qū)別為什么JsonValue的析構(gòu)函數(shù)不是純虛函數(shù)snprinf()Json數(shù)據(jù)中,”"“要進(jìn)行處理構(gòu)造函數(shù)非公有(public)(疑惑)解答:裝飾類,裝飾模式

為什么右值在傳值的時候還需要使用std::move(疑惑)數(shù)據(jù)一致性的實(shí)現(xiàn)匿名命名空間的作用

類的提前聲明

我覺得這個比較簡單,很好理解,因?yàn)樵贑語言中也有類似的語法:

int Temp(struct Exmp& value);

其中為什么要加上這個struct?就是為了告訴告訴編譯器:我這個類是存在的,只是它不在這個文件中,你先別報錯。

為什么定義函數(shù)的時候同時寫左值和右值作為傳參?

代碼如下:

Json(const object& values);

Json(object&& values);

右值不是可以用于初始化const左值引用嘛?為什么還需要單獨(dú)寫一個右值引用版本?

解答

其實(shí)可以不寫,因?yàn)橛抑悼梢赞D(zhuǎn)換成const左值引用,但是這會涉及到資源的所有權(quán)轉(zhuǎn)移(這里我也不是很了解,后面再補(bǔ)上吧),當(dāng)我們左值、右值情況都有相對應(yīng)的函數(shù)進(jìn)行處理的時候,一旦傳入是個右值,就優(yōu)先觸發(fā)移動拷貝構(gòu)造調(diào)用,使用移動語意,轉(zhuǎn)移資源,減少拷貝。

SFINAE機(jī)制(疑惑)

什么是SFINAE機(jī)制呢?這是一個縮寫,展開來即:Substitution Failure Is Not An Error(替換失敗不是錯誤),SFINAE是std::enable_if的模板別名。

[!ChatGPT] 在 C++ 模板編程中,SFINAE 是一種編譯技術(shù),它允許編譯器在模板參數(shù)推導(dǎo)或重載解析時忽略某些不符合條件的實(shí)例化選項(xiàng),而不會導(dǎo)致編譯錯誤。

代碼如下:

template

Json(const T& t) : Json(t.to_json()) {}

首先decltype應(yīng)該是見過的,和auto一樣用于自動類型推斷,class = dacltype(&T::to_json)就是想在類型T中找到那么個函數(shù)to_json,如果沒找到,就應(yīng)該換用別的構(gòu)造函數(shù),而應(yīng)該報錯;也就是說,模板中的第二個參數(shù)其實(shí)是對類型T的一個限定。

接下來我們再說說Json(t.to_json),由于對模板元編程不了解,一開始以為就是C++的顯式初始化列表,但是想起來沒有名為Json的成員變量,所以它的作用應(yīng)該是: 將t.to_json的返回值用于Json構(gòu)造函數(shù),但是具體是使用哪個重載函數(shù)就不一定了,看to_json的結(jié)果是什么。

這只是其中一段比較好理解的,還有根本看不懂的,等學(xué)了模板元編程再回來補(bǔ)吧:

template

std::is_constructible().begin()->first)>::value

&& std::is_constructible().begin()->second)>::value,

int>::type = 0>

Json(const M& m) : Json(object(m.begin(), m.end())) {}

指針類型可以被隱式轉(zhuǎn)換成bool類型

指針可以被隱式轉(zhuǎn)換成bool類型,這其實(shí)也好理解:

若是指針指向的是nullptr,則對應(yīng)的bool類型會是0; 否則就是1。

在Json中,有NULL這個類型,并且有對應(yīng)的Json構(gòu)造函數(shù),因此我們要避免出現(xiàn)異常,就需要禁用這種可能導(dǎo)致異常的隱式轉(zhuǎn)換:

Json(void*) = delete;

能夠隱式轉(zhuǎn)換成bool類型的數(shù)據(jù)

數(shù)值類型。這種情況是最常見的吧,所有的數(shù)字0為false,非零值都被認(rèn)為是1,即為true指針類型。此處就屬于這個情況,就補(bǔ)過多贅述了指針和數(shù)值類型的比較。應(yīng)該也挺好理解吧

為什么要同時有number_value和int_value?(疑惑)

其中有兩個獲取NUMBER類型的值的函數(shù):

/*

* 在該json項(xiàng)目中

* 不會區(qū)分整數(shù)和非整數(shù)

* number_value()和int_value()

* 疑惑:為什么不能就使用一個number_value完成所有操作?

*/

double number_value();

int int_value();

命名一個number_value()就能完成所有的任務(wù),為什么還需要后者呢? 原作者也說了,Json不區(qū)分NUMBER是整數(shù)還是非整數(shù)。

什么時候成員函數(shù)需要被聲明為靜態(tài)的?(疑惑)

size_t和std::string::size_type還是有區(qū)別

我們都知道size_t是unsigned int類型,而std::string::size_type也是unsigned int(這是我在初學(xué)C++的時候,在《C++primer》中看到的,所以我一直以為這兩個就是同一個東西。

在大多數(shù)情況下,size_t和std::string::size_type是一個東西,因此它們通??梢曰Q,但是也可能因?yàn)槠脚_的不同而出現(xiàn)些許的差異。

因此,為了程序的可移植性,還是使用std::string::size_type會更好,可以避免很多不必要的問題。 總結(jié):最好還是使用C++本身就定義了的東西,特別是在編寫庫的時候,因?yàn)椴恢莱绦驎谑裁聪到y(tǒng)中運(yùn)行,因此,程序的可移植性尤為重要。

為什么JsonValue的析構(gòu)函數(shù)不是純虛函數(shù)

class JsonValue{

protected:

// 為什么使用的是友元?

friend class Json;

friend class JsonInt;

friend class JsonDouble;

virtual Json::Type type() const = 0;

virtual bool equals(const JsonValue* other) const = 0;

virtual bool less(const JsonValue* other) const = 0;

virtual void dump(std::string& out) const = 0;

virtual double number_value() const;

virtual int int_value() const;

virtual bool bool_value() const;

virtual const std::string& string_value() const;

virtual const Json::array& array_items() const;

virtual const Json& operator[](size_t i) const;

virtual const Json::object& object_items() const;

virtual const Json& operator[](const std::string& key) const;

virtual ~JsonValue() {}

};

不難看出,這個類是一個抽象類,這里我就有一個疑問:為什么析構(gòu)函數(shù)沒設(shè)置成純虛的?而是提供了一個空實(shí)現(xiàn)? 因?yàn)槿绻鰳?gòu)函數(shù)也設(shè)置成了純虛函數(shù),繼承它的所有類都強(qiáng)制需要重寫析構(gòu)函數(shù),但是==這里提供了空實(shí)現(xiàn)的話,就可以使用編譯器默認(rèn)提供的析構(gòu)函數(shù)==,會省很多事,同時可以避免一些可能的bug。

snprinf()

// 第三個參數(shù)用于指定格式化形式

int snprintf(char* str, size_t maxlen, const char* format, ...)

之前就看到了這個,說說這個函數(shù)的作用吧:

snprintf函數(shù)用于將格式化的數(shù)據(jù)輸出到字符數(shù)組中,允許將數(shù)據(jù)格式化為指定格式的字符串。它以字符數(shù)組和格式化的方式工作,是一種基于C語言的函數(shù)。

上面提到了格式化的數(shù)據(jù),什么是格式化的數(shù)據(jù)呢?就是將數(shù)據(jù)以一定格式進(jìn)行處理,比如我們在使用printf輸出小數(shù)的時候,我們能對輸出的小數(shù)的位數(shù)進(jìn)行規(guī)定,就是這個意思。

之前就想到了使用stringstream做類似的操作,但是現(xiàn)在看來這里選擇使用snprintf()是有道理的。 stringstream由于是不定長的,它是動態(tài)管理內(nèi)存,而snprintf()是直接對字符數(shù)組進(jìn)行處理,在傳參的時候就已經(jīng)規(guī)定了緩沖區(qū)的大小,因此相比起stringstream,它的效率更高。 Json解析對性能有較高要求,因此更適合使用snprintf(),附上源碼:

static void dump(double value, string &out) {

if (std::isfinite(value)) {

char buf[32];

snprintf(buf, sizeof buf, "%.17g", value);

out += buf;

} else {

out += "null";

}

}

Json數(shù)據(jù)中,”"“要進(jìn)行處理

在對字符串的處理中,有如下內(nèi)容:

if (ch == '"') {

out += "\\\"";

}

因?yàn)樵?JSON 格式中,雙引號是用來界定字符串值的起始和結(jié)束的標(biāo)記,如果字符串中本身就含有雙引號,為避免與 JSON 字符串的雙引號沖突,需要進(jìn)行轉(zhuǎn)義處理。

這里可能需要去看看Json的內(nèi)容。

構(gòu)造函數(shù)非公有(public)(疑惑)

template

class Value : public JsonValue {

protected:

// Constructors

explicit Value(const T &value) : m_value(value) {}

explicit Value(T &&value) : m_value(move(value)) {}

// Get type tag

Json::Type type() const override {

return tag;

}

// Comparisons

bool equals(const JsonValue * other) const override {

return m_value == static_cast *>(other)->m_value;

}

bool less(const JsonValue * other) const override {

return m_value < static_cast *>(other)->m_value;

}

const T m_value;

void dump(string &out) const override { json11::dump(m_value, out); }

};

主要的疑惑就是在這個構(gòu)造函數(shù)上,它被聲明為protected的,和private一樣類外無法訪問。 豈不是說,我根本沒法創(chuàng)建Value類型的對象?那么,這么做有何用?

解答:裝飾類,裝飾模式

裝飾類是一種設(shè)計(jì)模式,屬于結(jié)構(gòu)性設(shè)計(jì)設(shè)計(jì)模式之一。 在裝飾模式中,我們可以動態(tài)地給一個對象添加一些額外的職能,而不需繼承自子類。這種模式通過創(chuàng)建一個包裝類來包裹一個原始類的對象。然后按需擴(kuò)展其功能。從而實(shí)現(xiàn)對對象的功能增強(qiáng)而不改變原有的類結(jié)構(gòu)。 在項(xiàng)目的后面,有很多其它的類繼承自該類,如:JsonObject、JsonInt等,這很符合裝飾模式的特點(diǎn)。 裝飾模式通常具有以下要素:

抽象構(gòu)件(Component):定義了對象的接口,可以是一個抽象類或者接口,聲明了對象的基本功能具體構(gòu)建(ConcreteComponent):實(shí)現(xiàn)了抽象構(gòu)建接口,是被裝飾的類裝飾者(Decorator):持有一個抽象構(gòu)件的引用并實(shí)現(xiàn)其接口,負(fù)責(zé)給對象動態(tài)添加新的功能具體裝飾者(ConcreteDecorator):實(shí)現(xiàn)了裝飾者的接口,并對具體構(gòu)件進(jìn)行裝飾。即:擴(kuò)展或改變核心功能

所以在該項(xiàng)目中,有個最原始的類JsonValue,它用來定義最原始的接口,然后再使用Value進(jìn)行裝飾,最后使用JsonObject等子類對功能進(jìn)行拓展。

為什么右值在傳值的時候還需要使用std::move(疑惑)

源碼如下:

explicit Value(T&& value) : m_value(move(value)) {}

明明接收的就是一個右值,為什么還使用move呢?

數(shù)據(jù)一致性的實(shí)現(xiàn)

struct Statics {

const std::shared_ptr null = make_shared();

const std::shared_ptr t = make_shared(true);

const std::shared_ptr f = make_shared(false);

const string empty_string;

const vector empty_vector;

const map empty_map;

Statics() {}

};

static const Statics & statics() {

static const Statics s {};

return s;

}

static const Json & static_null() {

// This has to be separate, not in Statics, because Json() accesses statics().null.

static const Json json_null;

return json_null;

}

在Json數(shù)據(jù)中,很多地方這些空值需要重復(fù)使用,但是只有全局變量使用的是默認(rèn)值初始化,這個類定義了各種類型的Json數(shù)據(jù)的初始值和空值,這樣可以避免一些隱藏的bug,并且使用靜態(tài)方法和常量,確保了程序的安全性。 當(dāng)我們想要初始化一個Json數(shù)據(jù)的時候,相對應(yīng)地使用這些已經(jīng)創(chuàng)建好的數(shù)據(jù)就行了。

匿名命名空間的作用

匿名命名空間用于限制命名空間內(nèi)的符號的作用域,使得這些符號只能在當(dāng)前編譯單元內(nèi)訪問,并且避免與其他編譯單元或全局作用域內(nèi)的相同名字的符號發(fā)生沖突。 上文中提到的編譯單元就是指的當(dāng)前源代碼文件。

在編譯過程中,每個源代碼文件會被編譯器單獨(dú)編譯成一個編譯單元,然后這些編譯單元最終會被鏈接,成為可執(zhí)行文件或者庫。

namespace{

...

}

在此處,我們將Json解析的一個類放在這個匿名空間中,用于監(jiān)控Json解析的狀態(tài)、進(jìn)度等。

柚子快報邀請碼778899分享:C++Json項(xiàng)目筆記

http://yzkb.51969.com/

相關(guān)文章

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/19543812.html

發(fā)布評論

您暫未設(shè)置收款碼

請?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄