2013-07-18 47 views
3

我在Visual C++ 2010中編寫函數重載程序。 以下是我的代碼在Visual C++中重載函數

// overload.cpp : Defines the entry point for the console application. 

#include<Windows.h> 
#include<iostream> 
#include<conio.h> 

using namespace std; 

//abs is overloaded in 3 types 
int abs(int i); 
double abs(double d); 
long abs(long f); 

void main() 
{ 
    cout<<abs(-10)<<"\n"; 
    cout<<abs(-11.0)<<"\n"; 
    cout<<abs(-9L)<<"\n"; 
    getch(); 
} 
int abs(int i) 
{ 
    cout<<"using integer abs()\n"; 
    return i>0? -i:i; 
} 
double abs(double d) 
{ 
    cout<<"using double abs()\n"; 
    return d>0? -d:d; 
} 
long abs (long l) 
{ 
    cout<<"using long abs()\n"; 
    return l>0?-l:l; 
} 

我有雙ABS和長ABS功能

1>c:\users\abc\documents\visual studio 2010\projects\overload\overload\overload.cpp(22): error C2084: function 'double abs(double)' already has a body 
1>c:\users\abc\documents\visual studio 2010\projects\overload\overload\overload.cpp(26): error C2084: function 'long abs(long)' already has a body 

爲什麼這個問題來了問題? 我已經將編譯從c改爲C++ 但最近我運行了另一個重載程序,它工作正常。我不知道該怎麼做?這裏是代碼。

#include<iostream> 
#include<cstdio> 
#include<conio.h> 
#include<cstring> 
using namespace std; 
void stradd(char*s1,char*s2); 
void stradd(char*s1,int i); 
void main() 
{ 
    char str[80]; 
    strcpy(str,"hello"); 
    stradd(str,"there"); 
    cout<<str<<"\n"; 
    getch(); 
} 
//concatenate a string with a "stringized "integer 
void stradd(char*s1,int i) 
{ 
    char temp[80]; 
    sprintf(temp,"%d",i); 
    strcat(s1,temp); 
} 
//concatenate 2 strings 
void stradd(char*s1,char *s2) 
{ 
    strcat(s1,s2); 
} 

和輸出hellothere

+9

您可能與'std :: abs'發生名稱衝突。嘗試命名它'absoluteValue'或別的東西,或者刪除'using namespace std;'並明確地寫'std :: cout'。 – stefan

+0

當我改變函數的名稱,然後它的工作,但那麼重載的重點是什麼。此外,我刪除命名空間,並寫了std :: cout,但仍然無法正常工作。 – Freedom911

+0

@ MsFreedom911,使用命名空間,你將擺脫這樣的問題,它是如此簡單 – SpongeBobFan

回答

5

您的問題來自abs針對某些類型(如double)聲明的標題。您不允許使用完全相同的頭文件(即相同的返回類型,相同的名稱,相同的參數列表,相同的限定符,例如const)。

有避免這種的方法有兩種:

  1. 使用標準庫:std::abs好,你不需要自己
  2. 命名任何你喜歡的方法absoluteValuemyAbs或實現它,但不是abs

第三種方法,即刪除using namespace std不會根據您的評論工作。這是因爲您包含Windows.h。這本身包括一堆標題,可能包括math.h。這在全局名稱空間中給出了一個名爲abs的方法。如果需要,最好不要包含Windows.h幷包括cmath。然後,abs只在名稱空間std中聲明,因此,您可以使用std::abs來調用它,它與abs不同。

+0

@ MsFreedom911問題在於在您的計算機上執行頭文件。作者可能有一個不同的,所以這在技術上不是他的錯。 – stefan

+0

我已經刪除了Windows頭文件,但仍然沒有運氣。我寫了其他程序,但這工作正常 – Freedom911

+0

@ MsFreedom911,刪除'#包括'和'使用命名空間標準;' – SpongeBobFan

4

當重載決議不能選擇一個功能獨特的最佳匹配,調用是不明確的。模糊的調用會產生編譯錯誤。

std已經有一個abs()具有以下特徵:

int abs (int n); 

所以,當你嘗試用doublelong它導致歧義編譯器重載它。

如果你是初學者學習編碼,我建議你使用庫中定義的函數名稱(至少包括你所包含的函數名稱)。在函數聲明和調用

Remove using namespace std; and explicitly write std::cout

OR

Re name your function to absoluteValue or something else

OR

使用明確的命名空間:

斯特凡已經給出的解決之道。 (未經測試,雖然它應該工作)

把你的功能放入classnamespace

也許this會爲您提供一點洞察力(來自SO)。

編輯:

第二個問題的stradd重載函數()不以任何其他庫中定義。這就是爲什麼沒有編譯錯誤。代碼中的以下功能簽名將導致錯誤:char * strcat (char * destination, const char * source)

+0

所以這意味着我們不能在C++中重載,或者我必須在C++的舊版編譯器上工作。 – Freedom911

+0

@ MsFreedom911你不能用你自己的方法替換現有的方法,如果這就是你的意思 – stefan

+0

@ MsFreedom911,你可以用'func(double param)'重載'func(int param)',但不能用另一個'func int param)'。如果你有兩個相同的函數,編譯器應該選擇什麼來調用? – SpongeBobFan

2

您的主要問題是您使用全局命名空間。只需在您自己的名稱空間中聲明您的函數,並且所有名稱衝突都將消失。
讓我解釋一下爲什麼會出現這些編譯時錯誤。
您在其中包含的標頭中的某處有double abs(double)long abs(long)函數。然後你自己創建具有相同簽名的函數。所以編譯器在你調用其中一個時不知道該使用什麼 - 有兩對相同的函數。所以它拒絕編譯,並且你得到這些錯誤。
所以你有2個選擇 - 希望每次你想創建一個函數時,你都會選擇一個唯一的名字,或者只是創建一個名字空間,而你的函數名應該是唯一的,只對你的名字空間中的其他函數是唯一的。
這不是關於超載 - void func(int i)重載void func(float f),但void func(int i)重寫void func(int i)。您可以在子類中重寫超類成員函數,但不能覆蓋獨立函數,如abs()