2010-10-12 102 views
4

我的教授給了我這個任務。函數模板中的邏輯錯誤

實現所謂 最大的通用功能,這需要通用 類型的3個參數,並返回最大這些 3.實現專門功能的char *類型。

這是我的代碼:

#include <iostream> 
#include <string> 

using namespace std; 

template<typename T> 
T Max(T first,T second,T third) 
{ 
    if(first > second) 
    { 
     if(first > third) 
     { 
      return first; 
     } 
     else 
     { 
      return third; 
     } 
    } 
    else if(second > third) 
    { 
     return second; 
    } 
    else 
    { 
     return third; 
    } 
} 


template<> 
char* Max(char* first,char* second,char* third) 
{ 
    if(strcmp(first, second) > 0) 
    { 
     if(strcmp(first, third) > 0) 
     { 
      return first; 
     } 
     else 
     { 
      return third; 
     } 
    } 
    else if(strcmp(second, third) > 0) 
    { 
     return second; 
    } 
    else 
    { 
     return third; 
    } 
} 

int main(void) 
{ 
    cout << "Greatest in 10, 20, 30 is " << Max(10, 20, 30) << endl; 

    char a = 'A'; 
    char b = 'B'; 
    char c = 'C'; 
    char Cptr = *Max(&a, &b, &c); 
    cout << "Greatest in A, B ,C is " << Cptr << endl; 

    string d = "A"; 
    string e = "B"; 
    string f = "C"; 
    string result = *Max(&d, &e, &f); 

    cout << "Greatest in A, B, C is " << result << endl; 
} 

輸出:

最大在10,20,30是30
最大在甲 ,B,C是C
A,B,C最大是 A

問題:

如果我在max函數一通char數據類型,B,C,它返回C,但是如果我傳遞字符串數據類型A,B,C,返回A.

爲什麼它在這裏返回A嗎?

回答

4

這裏有兩個問題。另外兩個答案已經在你的第三個電話中描述了這個問題。

但是你的第二個電話也錯:

char a = 'A'; 
char b = 'B'; 
char c = 'C'; 
char Cptr = *Max(&a, &b, &c); 

這將產生不確定的行爲,因爲strcmp預計零結尾的字符串,但這不是你喂什麼給函數。相反,你通過它指向個人char價值觀和strcmp有權利扼殺這一點。基本上,任何事情都可能發生,你的代碼工作是純粹的機會。

調用此重載將是正確的做法只是爲了打發char S,或通過C風格的字符串:

char C = Max(a, b, c); 

// or: 
char as[] = "a"; 
char bs[] = "b"; 
char cd[] = "c"; 
char* result = Max(as, bs, cd); 

或者,你可以直接把這個字符串字面量。

最後,關於風格的說明。您char*專業化,可以大大縮短,如果你通過傳入char*字符串轉換爲正確std::string S和重複使用的Max通用版「欺騙」一點點:

template<> 
char* Max(char* first,char* second,char* third) 
{ 
    return Max(string(first), string(second), string(third)); 
} 

(當然,這可能是效率較低但在大多數情況下,這可以安全地忽略)。

而又一個評論:該作業明確要求您專門爲char*功能模板,所以你的答案是正確的。然而,替代方案是過載而不是專門化它的功能。對於函數模板(而不是類模板),這是當你不需要更多的模板參數通常的方式:

char* Max(char* first,char* second,char* third) 
{ 
    return Max(string(first), string(second), string(third)); 
} 

注意,唯一的區別是在函數頭部的前失蹤template <>

2
string result = *Max(&d, &e, &f); 

這條線是你的問題。您正在將指針傳遞給該字符串,以便實際上返回最高指針地址。

請記住堆棧向下增長,所以堆棧的起始地址最高。每個後續的堆棧分配(即本例中的變量聲明)將啓動逐漸降低的堆棧地址,因此「A」顯示爲最大值。

如果你這樣寫:

string result = Max(d, e, f); 

你會得到你所期望的答案。

2

在第一種情況下,它使用模板特化,在第二種情況下使用通用模板。

但你的問題是你在第二種情況下調用Max方式:

string d = "A"; 
string e = "B"; 
string f = "C"; 
// you're comparing the string addresses here, not their content 
string result = *Max(&d, &e, &f); 

應該是:

string d = "A"; 
string e = "B"; 
string f = "C"; 
string result = Max(d, e, f); 

另外,我建議在char*專業化使用const指針,因爲它站立,你不能傳遞任何東西,但不是非常量指針,而不是常見的情況。

+0

感謝您的幫助。 – Searock 2010-10-12 08:56:00

1

代替

string result = *Max(*&d, &e, &f)

你需要

string result = Max(d.c_str(), e.c_str(), f.c_str()) 

需要注意的是,如果你的函數有const char*,而不是char*這會工作。如果你堅持使用char *的,這是錯誤的,那麼你就必須要拋棄常量性

string result = Max(const_cast<char*>(d.c_str()), 

const_cast<char*>(e.c_str()), const_cast<char*>(f.c_str())); 

但因爲使用的是string S,注意,你可以簡單地用== <>等對它們進行比較

+0

'c_str()'做什麼? – Searock 2010-10-12 08:45:50

+0

這不起作用:模板專門化只接受'char *'而不是'const char *'。此外,它會調用C-String的不必要的轉換。 – ereOn 2010-10-12 08:46:37

+0

c_str將字符串轉換爲常量字符* – 2010-10-12 08:47:13