2010-04-13 91 views
6

我們可以在C++程序中有兩個main()函數嗎?兩個主要功能

+2

你爲什麼想要? – wallyk 2010-04-13 02:17:13

+5

我在猜測一個不好的面試問題 – 2010-04-13 02:17:47

+0

'lex'和'flex'在'libl.a'或'libfl.a'中提供了自己的'main'(和'yywrap'),所以你可以寫一個詞法分析器不得不寫你自己的'主'。他們只是從'stdin'讀取。如果你想要自己的(幾乎總是),只需寫你自己的。 – 2010-04-13 03:31:21

回答

19

該標準明確地說,在3.6.1:

計劃須含有一種被稱爲全球主要的功能,這是該計劃的指定的開始。 [...] 該功能不得超載。

所以在程序的全局範圍內只能有一個main函數。其他範圍中也稱爲main的功能不受此影響,可以有任何數量的功能。

+8

用於引用標準 – 2010-04-13 02:42:55

2

在一個單一程序中,只允許一個入口點。

11

只有一個函數可以在任何名稱空間外被命名爲main,就像任何其他名稱一樣。如果您有名稱空間foobar(etc),您可以完美地擁有名爲foo::main,bar::main等的函數,但從系統角度來看,它們不會被視爲任何特殊的東西(僅限於任何名稱爲main以外的函數命名空間被特別處理,作爲程序的入口點)。當然,從您的main您可以完美地呼叫各種foo::main,bar::main等。

+1

實際上,通常可以有幾個具有相同名稱的函數,只要它們的參數不同... – sth 2010-04-13 02:23:08

+0

@James:是的,我更像是指「與其他任何名稱一樣」。全局函數'main'是個例外,這就是爲什麼我說一個函數*通常*會被重載。對於所有(?)其他函數,可能會有多個具有相同名稱的重載。 – sth 2010-04-13 02:35:57

4

您不能在全局範圍內重載main()。

8

是的!爲什麼不?

考慮下面的代碼:

namespace ps 
{ 
    int main(){return 0;} 
} 

int main() 
{ 
    ps::main(); 
} 

::main()將在執行過程中被調用。

3

一個程序只能有一個入口點,但當然一個main()函數可以根據您指定的任何邏輯調用其他函數。所以,如果你正在尋找一種方式來有效地編譯兩個或多個程序到一個可執行,你可以做這樣的事情:

int main(int argc, char ** argv) 
{ 
    if (argc > 0) // paranoia 
    { 
      if (strstr(argv[0], "frogger")) return frogger_main(argc, argv); 
     else if (strstr(argv[0], "pacman")) return pacman_main(argc, argv); 
     else if (strstr(argv[0], "tempest")) return tempest_main(argc, argv); 
    } 

    printf("Hmm, I'm not sure what I should run.\n"); 
    return 10; 
} 

...然後只需重命名你的「其他」的main()函數來frogger_main (),pacman_main()或任何您想要給他們的名字,並且如果可執行文件名中包含「frogger」這個單詞,那麼您將擁有一個運行爲Frogger的程序,或者如果可執行文件具有名稱'pacman'等。

1

哦,招數問題!

簡答:「這要看情況。」

龍答:正如其他人所指出的那樣,你可以在不同的命名空間命名爲main,只要它們是多重功能,且只能在根命名空間的main(即::main)作爲主程序。事實上,一些線程庫的線程類有一個名爲main的方法,庫用戶用他們想要在線程中運行的代碼覆蓋。

現在,假設你沒有做任何的命名空間的技巧,如果你試圖在兩個不同的.cpp文件來定義::main,自己都將編譯的文件,但是,連接器將中止,因爲有一個名爲main兩個定義;它無法分辨哪個鏈接。

(A問題,我對大師們在那裏:在C++中,執行函數定義int main() {}extern "C" int main() {}產生具有相同簽名功能,我還沒有嘗試過自己。)

現在的時間如果一個main位於庫(.a或.so文件)中,並且另一個位於您的源((.a或.so)文件)中,則可以在程序的源文件中包含多個::main。o)文件,源文件中的文件將被取消,並且庫中的文件將被刪除,和鏈接將成功,除非出現其他問題!如果你沒有寫一個main,圖書館的main會贏。這實際上在lexyacc的支持庫中完成;他們提供了一個準系統main,所以你不必爲快速解析器編寫一個。

這導致了一個有趣的應用:爲每個庫提供main。我的圖書館往往很小並且很專注,所以我在每個圖書館都放了一個main.cpp,這個圖書館的測試或實用程序代碼爲main。例如,我的共享內存庫有一個main,它允許從命令行調用管理共享內存的所有功能。然後我可以使用bash腳本測試各種情況。任何共享內存庫中的鏈接都可以免費獲得測試代碼,或者只需定義自己的main即可處置。

編輯:只是爲了確保人們都在概念清楚,我說的是一個構建,看起來像:

gcc -c -o bar_main.o bar_main.cpp 
ar -r libbar.a bar_main.o 
ranlib libbar.a 
gcc -c -o foo_main.o foo_main.cpp 
gcc -o foo foo_main.o -L. -lbar 

在這個例子中,在foo_main.omain擊敗在bar_main.omain。該標準沒有定義這種行爲,因爲他們不在乎。無論如何,人們使用很多非標準的東西; Linux是一個使用C位域的例子。 ld這種方式比我已經知道如何輸入更長。

說真的,夥計們,如果你需要轉化出最小公分母的代碼,請隨時嚴格遵守標準。但是,如果您有能力建立lexyacc計劃的平臺上的奢侈品,請務必充分利用它。

+2

未定義的行爲可能包含您觀察到的行爲。這並不意味着「你可以有一個以上」和「你的來源中的一個獲勝」,這只是意味着你的實現爲你選擇了這種行爲。太糟糕了,只是等到你的顧客得到不太快樂的結果。 – 2010-04-13 02:40:13

+0

這隻有在第一個'main'被聲明爲弱符號時纔有效。如果你有一個弱符號和一個常規符號,常規符號和弱符號都會被丟棄。如果你有兩個弱符號,其中一個以某種方式獲勝。如果您有兩個常規符號,那是錯誤的。 – 2010-04-13 02:47:29

+0

@Windows:自從gcc 2.7.2.2開始,我們已經做了12年,現在沒有任何問題。但是,我們的目標是Linux,所以也許這是Windows-vs-everything的其他事情。 @Adam:假設你在談論Unix,聽起來像我們的圖書館符號默認爲弱。 – 2010-04-13 03:09:32

0

在全局範圍內只有一個入口點。