2010-06-11 57 views
40

我有一個超類是這樣的:避免警告「未引用的形式參數」

class Parent 
{ 
public: 
    virtual void Function(int param); 
}; 

void Parent::Function(int param) 
{ 
    std::cout << param << std::endl; 
} 

..和一個子類是這樣的:

class Child : public Parent 
{ 
public: 
    void Function(int param); 
}; 

void Child::Function(int param) 
{ 
    ;//Do nothing 
} 

當我編譯的子類。 CPP文件,我得到這個錯誤

warning C4100: 'param' : unreferenced formal parameter 

作爲一種做法,我們曾經把警告視爲錯誤。如何避免上述警告?

謝謝。

+0

使用boost :: ignore_unused(param)http://stackoverflow.com/a/24310846/888576 – 2016-02-03 17:37:18

回答

71

在C++中,你不必給你不使用名稱的參數,所以你可以只是這樣做:

void Child::Function(int) 
{ 
    //Do nothing 
} 

您可能希望保留參數名稱在聲明儘管如此,通過文檔方式的頭文件。空的陳述(;)也是不必要的。

+1

@ Charles..If函數是內聯的,這樣做是否合法? 'class Child:public Parent {public:void Function(int/* param */= 0,int param2 = 0){std :: cout << param2 << std :: endl; }};' – bdhar 2010-06-11 06:46:28

+0

你的意思是有一個默認值的無名參數。我不是100%確定的,但我認爲這是合法的。我不知道爲什麼不在任何情況下。 – 2010-06-11 07:14:23

+3

@bdhar:請注意,在層次結構的不同級別提供默認參數是非常危險的,除非您的默認值一致。你可以得到的問題是,從兩個上下文中調用相同的函數可能最終會調用具有不同默認值的相同的最終覆蓋:struct base {virtual void f(int i = 0); }; struct derived:base {virtual void f(int i = 5); }; int main(){derived d; base&b = d; d.f()/ * D :: f(5)* /; b.f();/* D :: f(0)* /}' – 2010-06-11 07:35:08

17

,如果你想保持參數名稱,您可以使用另一種方法是轉換爲void:

void Child::Function(int param) 
{ 
    (void)param; //Do nothing 
} 
+0

對於像int這樣的內置類型可以,但如果參數是對不完整類型的引用,則將其轉換爲void將引入對需要查看的類型的完整定義的需求,而在此之前不存在此類需要。 – TheBeardyMan 2012-01-19 14:23:26

+0

這是C語言的解決方案,非常有用。 – Bentoy13 2013-11-14 16:47:04

+1

Qt的Q_UNUSED宏是一個稍微更花哨的版本。 – 2014-09-06 22:01:14

8

由於@Charles貝利提到的,你可以跳過參數名稱。

但是,在某些情況下,您需要參數名稱,因爲在調試版本中,您要調用ASSERT(),但在零售版本上它是nop。對於那些場景有一個方便的宏(至少在VC++ :-))UNREFERENCED_PARAMETER(),這是這樣定義的:

#define UNREFERENCED_PARAMETER(x) x 

注意的是,簡單的投@R塞繆爾Klatchko貼也可以,但是我個人覺得它更如果代碼明確表示這是一個未引用的參數,而不是像這樣的簡單的不明原因轉換,則可讀。

+1

隱藏在宏觀背後是一個好主意(你是對的,那麼我的例子就更清楚了)。也就是說,你應該把這個強制轉換添加到你的宏中,否則你可能會得到一個警告(在g ++ 4.2.1上,我得到'warning:statement沒有任何效果) – 2010-06-11 06:49:23

+0

你可以定義ASSERT(param) (空隙)PARAM。您的UNREFERENCED_PARAMETER表示完全沒有引用。但它可以被引用 - 在ASSERT中。 – harper 2010-06-11 07:41:46

26

我更喜歡使用宏,因爲它不僅告訴編譯器我的意圖,還告訴代碼的其他維護者,並且稍後可以搜索它。

評論參數名稱的方法很容易被不熟悉代碼的人(或6個月後的我)忽略。

然而,這是一個風格問題,在代碼生成,性能或健壯性方面,兩種方法都不是「更好」或更優化。對我而言,決定性的因素是通過一個標準化系統向他人通報我的意圖。省略參數名稱和投入評論將發揮同樣的

void CFooBar::OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult) 
{ 
    UNREFERENCED_PARAMETER(pNMHDR); 

或者:

void CFooBar::OnLvnItemchanged(NMHDR* /* pNMHDR */, LRESULT *pResult) 
{ 
    // Not using: pNMHDR 

我會說,最糟糕的解決方案是抑制警告信息;那會影響你的整個文件或項目,你會失去知識,也許你錯過了一些東西。至少通過添加宏或者註釋參數名稱,你告訴其他人你已經做出了一個有意識的決定,不使用這個參數,並且這不是一個錯誤。

WinNT中的Windows SDK。h定義了UNREFERENCED_PARAMETER()以及DBG_UNREFERENCED_PARAMETER()DBG_UNREFERENCED_LOCAL_VARIABLE()。它們都是以相同的方式進行評估,但不同之處在於,當您開始時會使用DBG_UNREFERENCED_PARAMETER(),並希望在代碼更完整時使用該參數。如果您確定永遠不會使用該參數,請使用UNREFERENCED_PARAMETER()版本。

Microsoft基礎類(MFC)具有類似的約定,其中較短的UNUSED()UNUSED_ALWAYS()宏。

選擇一種風格,堅持下去。這樣以後,您可以在代碼中搜索「DBG_UNREFERENCED_PARAMETER」,並查找您希望使用參數的位置的任何實例,但不會。通過採用一致的風格,並習慣性地使用它,以後可以讓其他人更容易。

+1

評論參數名稱絕對是我認爲的最佳實踐,也是最具可讀性的。 – 2014-02-12 21:53:21

+1

@DavidKirby如果你的ifdef函數內部使用了參數,那麼你不能使用註釋掉的名字,這取決於define。 – 2014-04-05 11:57:56

+1

註釋掉的參數應該是NMHDR */* pNMHDR * /不是NMHDR/* * pNMHDR * /如上所述,這是一個更改函數簽名的錯誤。更一般地說,不要在類型和星號之間加一個空格:NMHDR * pNMHDR – 2015-11-18 21:36:21

4

我會使用宏來抑制未引用的形式參數警告:

#define UNUSED(x) (&reinterpret_cast< const int& >(x)) 

這具有以下優點:

  • 不同的#define未使用(X)(無效)X,它不不會引入參數類型完整定義的需求,在以前沒有這種需求的情況下可以看到。
  • 與#define UNUSED(x)& x不同,它可以安全地使用其參數類型超載一元操作符&。
2

Pragma很好地工作,因爲它很清楚你正在使用VS.此警告具有非常高的噪聲與收益比,因爲未回調的參數在回調接口和派生方法中非常常見。即使是Microsoft Windows中的團隊誰使用W4已經成爲厭倦了無意義的(會更適合用於/壁),並簡單地添加到他們的項目:

#pragma warning(disable: 4100) 

如果你想減輕預警只是一個代碼塊,圍繞着它:

#pragma warning(push) 
#pragma warning(disable: 4100) 
void SomeCallbackOrOverride(int x, float y) { } 
#pragma warning(pop) 

離開了參數名的實踐中,你不能輕易地通過名稱檢查,也沒有把它添加到手錶(調試器的缺點,如果你有一個以上的變得混亂未引用的參數),並且雖然方法的特定實現可能不使用該參數,但瞭解其值可以幫助您計算出whi你正處於一個過程的階段,特別是當你沒有整個調用堆棧時。