c++的.h和.cpp為什么分開

一胆胰、C++ 編譯模式
通常刻获,在一個 C++ 程序中蝎毡,只包含兩類文件—— .cpp 文件和 .h 文件。其中痒筒,.cpp 文件被稱作 C++ 源文件茬贵,里面放的都是 C++ 的源代碼解藻;而 .h 文件則被稱作 C++ 頭文件,里面放的也是 C++ 的源代碼葡盗。

C++ 語言支持"分別編譯"(separatecompilation)螟左。也就是說,一個程序所有的內(nèi)容觅够,可以分成不同的部分分別放在不同的 .cpp 文件里胶背。.cpp 文件里的東西都是相對獨(dú)立的,在編譯(compile)時(shí)不需要與其他文件互通喘先,只需要在編譯成目標(biāo)文件后再與其他的目標(biāo)文件做一次鏈接(link)就行了钳吟。比如,在文件 a.cpp 中定義了一個全局函數(shù) "void a(){}"窘拯,而在文件 b.cpp 中需要調(diào)用這個函數(shù)红且。即使這樣,文件 a.cpp 和文件 b.cpp 并不需要相互知道對方的存在涤姊,而是可以分別地對它們進(jìn)行編譯暇番,編譯成目標(biāo)文件之后再鏈接,整個程序就可以運(yùn)行了思喊。

這是怎么實(shí)現(xiàn)的呢壁酬?從寫程序的角度來講,很簡單恨课。在文件 b.cpp 中舆乔,在調(diào)用 "void a()" 函數(shù)之前,先聲明一下這個函數(shù) "voida();"庄呈,就可以了蜕煌。這是因?yàn)榫幾g器在編譯 b.cpp 的時(shí)候會生成一個符號表(symbol table),像 "void a()" 這樣的看不到定義的符號诬留,就會被存放在這個表中斜纪。再進(jìn)行鏈接的時(shí)候,編譯器就會在別的目標(biāo)文件中去尋找這個符號的定義文兑。一旦找到了盒刚,程序也就可以順利地生成了。

注意這里提到了兩個概念绿贞,一個是"定義"因块,一個是"聲明"。簡單地說籍铁,"定義"就是把一個符號完完整整地描述出來:它是變量還是函數(shù)涡上,返回什么類型趾断,需要什么參數(shù)等等。而"聲明"則只是聲明這個符號的存在吩愧,即告訴編譯器芋酌,這個符號是在其他文件中定義的,我這里先用著雁佳,你鏈接的時(shí)候再到別的地方去找找看它到底是什么吧脐帝。定義的時(shí)候要按 C++ 語法完整地定義一個符號(變量或者函數(shù)),而聲明的時(shí)候就只需要寫出這個符號的原型了糖权。需要注意的是堵腹,一個符號,在整個程序中可以被聲明多次星澳,但卻要且僅要被定義一次疚顷。試想,如果一個符號出現(xiàn)了兩種不同的定義募判,編譯器該聽誰的荡含?
這種機(jī)制給 C++ 程序員們帶來了很多好處咒唆,同時(shí)也引出了一種編寫程序的方法届垫。考慮一下全释,如果有一個很常用的函數(shù) "void f() {}"装处,在整個程序中的許多 .cpp 文件中都會被調(diào)用,那么浸船,我們就只需要在一個文件中定義這個函數(shù)妄迁,而在其他的文件中聲明這個函數(shù)就可以了。一個函數(shù)還好對付李命,聲明起來也就一句話登淘。但是,如果函數(shù)多了封字,比如是一大堆的數(shù)學(xué)函數(shù)黔州,有好幾百個,那怎么辦阔籽?能保證每個程序員都可以完完全全地把所有函數(shù)的形式都準(zhǔn)確地記下來并寫出來嗎流妻?

二、什么是頭文件
很顯然笆制,答案是不可能绅这。但是有一個很簡單地辦法,可以幫助程序員們省去記住那么多函數(shù)原型的麻煩:我們可以把那幾百個函數(shù)的聲明語句全都先寫好在辆,放在一個文件里证薇,等到程序員需要它們的時(shí)候度苔,就把這些東西全部 copy 進(jìn)他的源代碼中。

這個方法固然可行浑度,但還是太麻煩林螃,而且還顯得很笨拙。于是俺泣,頭文件便可以發(fā)揮它的作用了疗认。所謂的頭文件,其實(shí)它的內(nèi)容跟 .cpp 文件中的內(nèi)容是一樣的伏钠,都是 C++ 的源代碼横漏。但頭文件不用被編譯。我們把所有的函數(shù)聲明全部放進(jìn)一個頭文件中熟掂,當(dāng)某一個 .cpp 源文件需要它們時(shí)缎浇,它們就可以通過一個宏命令 "#include" 包含進(jìn)這個 .cpp 文件中,從而把它們的內(nèi)容合并到 .cpp 文件中去赴肚。當(dāng) .cpp 文件被編譯時(shí)素跺,這些被包含進(jìn)去的 .h 文件的作用便發(fā)揮了。

舉一個例子吧誉券,假設(shè)所有的數(shù)學(xué)函數(shù)只有兩個:f1 和 f2指厌,那么我們把它們的定義放在 math.cpp 里:

/* math.cpp /
double f1()
{
//do something here....
return;
}
double f2(double a)
{
//do something here...
return a * a;
}
/ end of math.cpp */
并把"這些"函數(shù)的聲明放在一個頭文件 math.h 中:

/* math.h /
double f1();
double f2(double);
/ end of math.h */
在另一個文件main.cpp中,我要調(diào)用這兩個函數(shù)踊跟,那么就只需要把頭文件包含進(jìn)來:

/* main.cpp */

include "math.h"
main()
{
int number1 = f1();
int number2 = f2(number1);
}
/* end of main.cpp */
這樣踩验,便是一個完整的程序了。需要注意的是商玫,.h 文件不用寫在編譯器的命令之后箕憾,但它必須要在編譯器找得到的地方(比如跟 main.cpp 在一個目錄下)main.cpp 和 math.cpp 都可以分別通過編譯,生成 main.o 和 math.o拳昌,然后再把這兩個目標(biāo)文件進(jìn)行鏈接袭异,程序就可以運(yùn)行了。

三炬藤、#include
include 是一個來自 C 語言的宏命令御铃,它在編譯器進(jìn)行編譯之前,即在預(yù)編譯的時(shí)候就會起作用刻像。#include 的作用是把它后面所寫的那個文件的內(nèi)容畅买,完完整整地、一字不改地包含到當(dāng)前的文件中來细睡。值得一提的是谷羞,它本身是沒有其它任何作用與副功能的,它的作用就是把每一個它出現(xiàn)的地方,替換成它后面所寫的那個文件的內(nèi)容湃缎。簡單的文本替換犀填,別無其他。因此嗓违,main.cpp 文件中的第一句(#include"math.h")九巡,在編譯之前就會被替換成 math.h 文件的內(nèi)容。即在編譯過程將要開始的時(shí)候蹂季,main.cpp 的內(nèi)容已經(jīng)發(fā)生了改變:
/* ~main.cpp /
double f1();
double f2(double);
main()
{
int number1 = f1();
int number2 = f2(number1);
}
/ end of ~main.cpp */
不多不少冕广,剛剛好。同理可知偿洁,如果我們除了 main.cpp 以外撒汉,還有其他的很多 .cpp 文件也用到了 f1 和 f2 函數(shù)的話,那么它們也通通只需要在使用這兩個函數(shù)前寫上一句 #include "math.h" 就行了涕滋。

四睬辐、頭文件中應(yīng)該寫什么
通過上面的討論,我們可以了解到宾肺,頭文件的作用就是被其他的 .cpp 包含進(jìn)去的溯饵。它們本身并不參與編譯,但實(shí)際上锨用,它們的內(nèi)容卻在多個 .cpp 文件中得到了編譯丰刊。通過"定義只能有一次"的規(guī)則,我們很容易可以得出黔酥,頭文件中應(yīng)該只放變量和函數(shù)的聲明藻三,而不能放它們的定義洪橘。因?yàn)橐粋€頭文件的內(nèi)容實(shí)際上是會被引入到多個不同的 .cpp 文件中的跪者,并且它們都會被編譯。放聲明當(dāng)然沒事熄求,如果放了定義渣玲,那么也就相當(dāng)于在多個文件中出現(xiàn)了對于一個符號(變量或函數(shù))的定義,縱然這些定義都是相同的弟晚,但對于編譯器來說忘衍,這樣做不合法。

所以卿城,應(yīng)該記住的一點(diǎn)就是枚钓,.h頭文件中,只能存在變量或者函數(shù)的聲明瑟押,而不要放定義搀捷。即,只能在頭文件中寫形如:extern int a; 和 void f(); 的句子。這些才是聲明嫩舟。如果寫上 inta;或者 void f() {} 這樣的句子氢烘,那么一旦這個頭文件被兩個或兩個以上的 .cpp 文件包含的話,編譯器會立馬報(bào)錯家厌。(關(guān)于 extern播玖,前面有討論過,這里不再討論定義跟聲明的區(qū)別了饭于。)

但是蜀踏,這個規(guī)則是有三個例外的:

一,頭文件中可以寫 const 對象的定義掰吕。因?yàn)槿值?const 對象默認(rèn)是沒有 extern 的聲明的脓斩,所以它只在當(dāng)前文件中有效。把這樣的對象寫進(jìn)頭文件中畴栖,即使它被包含到其他多個 .cpp 文件中随静,這個對象也都只在包含它的那個文件中有效,對其他文件來說是不可見的吗讶,所以便不會導(dǎo)致多重定義燎猛。同時(shí),因?yàn)檫@些 .cpp 文件中的該對象都是從一個頭文件中包含進(jìn)去的照皆,這樣也就保證了這些 .cpp 文件中的這個 const 對象的值是相同的重绷,可謂一舉兩得。同理膜毁,static 對象的定義也可以放進(jìn)頭文件昭卓。
二,頭文件中可以寫內(nèi)聯(lián)函數(shù)(inline)的定義瘟滨。因?yàn)閕nline函數(shù)是需要編譯器在遇到它的地方根據(jù)它的定義把它內(nèi)聯(lián)展開的候醒,而并非是普通函數(shù)那樣可以先聲明再鏈接的(內(nèi)聯(lián)函數(shù)不會鏈接),所以編譯器就需要在編譯時(shí)看到內(nèi)聯(lián)函數(shù)的完整定義才行杂瘸。如果內(nèi)聯(lián)函數(shù)像普通函數(shù)一樣只能定義一次的話倒淫,這事兒就難辦了。因?yàn)樵谝粋€文件中還好败玉,我可以把內(nèi)聯(lián)函數(shù)的定義寫在最開始敌土,這樣可以保證后面使用的時(shí)候都可以見到定義;但是运翼,如果我在其他的文件中還使用到了這個函數(shù)那怎么辦呢返干?這幾乎沒什么太好的解決辦法,因此 C++ 規(guī)定血淌,內(nèi)聯(lián)函數(shù)可以在程序中定義多次矩欠,只要內(nèi)聯(lián)函數(shù)在一個 .cpp 文件中只出現(xiàn)一次,并且在所有的 .cpp 文件中,這個內(nèi)聯(lián)函數(shù)的定義是一樣的晚顷,就能通過編譯峰伙。那么顯然,把內(nèi)聯(lián)函數(shù)的定義放進(jìn)一個頭文件中是非常明智的做法该默。
三瞳氓,頭文件中可以寫類(class)的定義。因?yàn)樵诔绦蛑袆?chuàng)建一個類的對象時(shí)栓袖,編譯器只有在這個類的定義完全可見的情況下匣摘,才能知道這個類的對象應(yīng)該如何布局,所以裹刮,關(guān)于類的定義的要求音榜,跟內(nèi)聯(lián)函數(shù)是基本一樣的。所以把類的定義放進(jìn)頭文件捧弃,在使用到這個類的 .cpp 文件中去包含這個頭文件赠叼,是一個很好的做法。在這里违霞,值得一提的是嘴办,類的定義中包含著數(shù)據(jù)成員和函數(shù)成員。數(shù)據(jù)成員是要等到具體的對象被創(chuàng)建時(shí)才會被定義(分配空間)买鸽,但函數(shù)成員卻是需要在一開始就被定義的涧郊,這也就是我們通常所說的類的實(shí)現(xiàn)。一般眼五,我們的做法是妆艘,把類的定義放在頭文件中,而把函數(shù)成員的實(shí)現(xiàn)代碼放在一個 .cpp 文件中看幼。這是可以的批旺,也是很好的辦法。不過桌吃,還有另一種辦法朱沃。那就是直接把函數(shù)成員的實(shí)現(xiàn)代碼也寫進(jìn)類定義里面。在 C++ 的類中茅诱,如果函數(shù)成員在類的定義體中被定義,那么編譯器會視這個函數(shù)為內(nèi)聯(lián)的搬卒。因此瑟俭,把函數(shù)成員的定義寫進(jìn)類定義體,一起放進(jìn)頭文件中契邀,是合法的摆寄。注意一下,如果把函數(shù)成員的定義寫在類定義的頭文件中,而沒有寫進(jìn)類定義中微饥,這是不合法的逗扒,因?yàn)檫@個函數(shù)成員此時(shí)就不是內(nèi)聯(lián)的了。一旦頭文件被兩個或兩個以上的 .cpp 文件包含欠橘,這個函數(shù)成員就被重定義了矩肩。
五、頭文件中的保護(hù)措施
考慮一下肃续,如果頭文件中只包含聲明語句的話黍檩,它被同一個 .cpp 文件包含再多次都沒問題——因?yàn)槁暶髡Z句的出現(xiàn)是不受限制的。然而始锚,上面討論到的頭文件中的三個例外也是頭文件很常用的一個用處刽酱。那么,一旦一個頭文件中出現(xiàn)了上面三個例外中的任何一個瞧捌,它再被一個 .cpp 包含多次的話棵里,問題就大了。因?yàn)檫@三個例外中的語法元素雖然"可以定義在多個源文件中"姐呐,但是"在一個源文件中只能出現(xiàn)一次"衍慎。設(shè)想一下,如果 a.h 中含有類 A 的定義皮钠,b.h 中含有類 B 的定義稳捆,由于類B的定義依賴了類 A,所以 b.h 中也 #include了a.h÷蠛洌現(xiàn)在有一個源文件乔夯,它同時(shí)用到了類A和類B,于是程序員在這個源文件中既把 a.h 包含進(jìn)來了款侵,也把 b.h 包含進(jìn)來了末荐。這時(shí),問題就來了:類A的定義在這個源文件中出現(xiàn)了兩次新锈!于是整個程序就不能通過編譯了甲脏。你也許會認(rèn)為這是程序員的失誤——他應(yīng)該知道 b.h 包含了 a.h ——但事實(shí)上他不應(yīng)該知道。

使用 "#define" 配合條件編譯可以很好地解決這個問題妹笆。在一個頭文件中块请,通過 #define 定義一個名字,并且通過條件編譯 #ifndef...#endif 使得編譯器可以根據(jù)這個名字是否被定義拳缠,再決定要不要繼續(xù)編譯該頭文中后續(xù)的內(nèi)容墩新。這個方法雖然簡單,但是寫頭文件時(shí)一定記得寫進(jìn)去窟坐。

C++ 頭文件和源文件的區(qū)別
一海渊、源文件如何根據(jù) #include 來關(guān)聯(lián)頭文件
1绵疲、系統(tǒng)自帶的頭文件用尖括號括起來,這樣編譯器會在系統(tǒng)文件目錄下查找臣疑。
2盔憨、用戶自定義的文件用雙引號括起來,編譯器首先會在用戶目錄下查找讯沈,然后在到 C++ 安裝目錄(比如 VC 中可以指定和修改庫文件查找路徑郁岩,Unix 和 Linux 中可以通過環(huán)境變量來設(shè)定)中查找,最后在系統(tǒng)文件中查找芙盘。

include "xxx.h"(我一直以為 "" 和 <> 沒什么區(qū)別驯用,但是 tinyxml.h 是非系統(tǒng)下的都文件,所以要用 "")
二儒老、頭文件如何來關(guān)聯(lián)源文件
這個問題實(shí)際上是說蝴乔,已知頭文件 "a.h" 聲明了一系列函數(shù),"b.cpp" 中實(shí)現(xiàn)了這些函數(shù)驮樊,那么如果我想在 "c.cpp" 中使用 "a.h" 中聲明的這些在 "b.cpp"中實(shí)現(xiàn)的函數(shù)薇正,通常都是在 "c.cpp" 中使用 #include "a.h",那么 c.cpp 是怎樣找到 b.cpp 中的實(shí)現(xiàn)呢囚衔?

其實(shí) .cpp 和 .h 文件名稱沒有任何直接關(guān)系挖腰,很多編譯器都可以接受其他擴(kuò)展名。比如偶現(xiàn)在看到偶們公司的源代碼练湿,.cpp 文件由 .cc 文件替代了猴仑。

在 Turbo C 中,采用命令行方式進(jìn)行編譯肥哎,命令行參數(shù)為文件的名稱辽俗,默認(rèn)的是 .cpp 和 .h,但是也可以自定義為 .xxx 等等篡诽。

譚浩強(qiáng)老師的《C 程序設(shè)計(jì)》一書中提到崖飘,編譯器預(yù)處理時(shí),要對 #include 命令進(jìn)行"文件包含處理":將 file2.c 的全部內(nèi)容復(fù)制到 #include "file2.c" 處杈女。這也正說明了朱浴,為什么很多編譯器并不 care 到底這個文件的后綴名是什么----因?yàn)?#include 預(yù)處理就是完成了一個"復(fù)制并插入代碼"的工作。

編譯的時(shí)候达椰,并不會去找 b.cpp 文件中的函數(shù)實(shí)現(xiàn)翰蠢,只有在 link 的時(shí)候才進(jìn)行這個工作。我們在 b.cpp 或 c.cpp 中用 #include "a.h" 實(shí)際上是引入相關(guān)聲明砰碴,使得編譯可以通過躏筏,程序并不關(guān)心實(shí)現(xiàn)是在哪里,是怎么實(shí)現(xiàn)的呈枉。源文件編譯后成生了目標(biāo)文件(.o 或 .obj 文件)趁尼,目標(biāo)文件中,這些函數(shù)和變量就視作一個個符號猖辫。在 link 的時(shí)候酥泞,需要在 makefile 里面說明需要連接哪個 .o 或 .obj 文件(在這里是 b.cpp 生成的 .o 或 .obj 文件),此時(shí)啃憎,連接器會去這個 .o 或 .obj 文件中找在 b.cpp 中實(shí)現(xiàn)的函數(shù)芝囤,再把他們 build 到 makefile 中指定的那個可以執(zhí)行文件中。

在 Unix下辛萍,甚至可以不在源文件中包括頭文件悯姊,只需要在 makefile 中指名即可(不過這樣大大降低了程序可讀性,是個不好的習(xí)慣哦_)贩毕。在 VC 中悯许,一幫情況下不需要自己寫 makefile,只需要將需要的文件都包括在 project中辉阶,VC 會自動幫你把 makefile 寫好先壕。

通常,C++ 編譯器會在每個 .o 或 .obj 文件中都去找一下所需要的符號谆甜,而不是只在某個文件中找或者說找到一個就不找了垃僚。因此,如果在幾個不同文件中實(shí)現(xiàn)了同一個函數(shù)规辱,或者定義了同一個全局變量谆棺,鏈接的時(shí)候就會提示 "redefined"。

綜上所訴
.h文件中能包含:

類成員數(shù)據(jù)的聲明罕袋,但不能賦值
類靜態(tài)數(shù)據(jù)成員的定義和賦值改淑,但不建議,只是個聲明就好炫贤。
類的成員函數(shù)的聲明
非類成員函數(shù)的聲明
常數(shù)的定義:如:constint a=5;
靜態(tài)函數(shù)的定義
類的內(nèi)聯(lián)函數(shù)的定義
不能包含:

1. 所有非靜態(tài)變量(不是類的數(shù)據(jù)成員)的聲明
2溅固。 默認(rèn)命名空間聲明不要放在頭文件,using namespace std;等應(yīng)放在.cpp中兰珍,在 .h 文件中使用 std::string

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侍郭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子掠河,更是在濱河造成了極大的恐慌亮元,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唠摹,死亡現(xiàn)場離奇詭異爆捞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)勾拉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門煮甥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盗温,“玉大人,你說我怎么就攤上這事成肘÷艟郑” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵双霍,是天一觀的道長砚偶。 經(jīng)常有香客問我,道長洒闸,這世上最難降的妖魔是什么染坯? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮丘逸,結(jié)果婚禮上单鹿,老公的妹妹穿的比我還像新娘。我一直安慰自己鸣个,他們只是感情好羞反,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著囤萤,像睡著了一般昼窗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涛舍,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天澄惊,我揣著相機(jī)與錄音,去河邊找鬼富雅。 笑死掸驱,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的没佑。 我是一名探鬼主播毕贼,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蛤奢!你這毒婦竟也來了鬼癣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤啤贩,失蹤者是張志新(化名)和其女友劉穎待秃,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痹屹,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡章郁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了志衍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暖庄。...
    茶點(diǎn)故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡聊替,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雄驹,到底是詐尸還是另有隱情佃牛,我是刑警寧澤淹辞,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布医舆,位于F島的核電站,受9級特大地震影響象缀,放射性物質(zhì)發(fā)生泄漏蔬将。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一央星、第九天 我趴在偏房一處隱蔽的房頂上張望霞怀。 院中可真熱鬧,春花似錦莉给、人聲如沸毙石。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽徐矩。三九已至,卻和暖如春叁幢,著一層夾襖步出監(jiān)牢的瞬間滤灯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工曼玩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鳞骤,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓黍判,卻偏偏與公主長得像豫尽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子顷帖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容