2014-03-12 120 views
1

實際上我有兩個問題。多行宏(C++)中的If-else語句

  1. 這是 「如果(ClassPtr1)& &(ClassPtr2)」 正確的方法來檢查,如果他們不爲空?

  2. 我想知道是否有可能在多行宏中完全包含if else語句。我附上了示例代碼。

    #define MACRO_NAME(object,expression){\ 
    Class1* ClassPtr1 = dynamic_cast<Class1*>(object);\ 
    Class2* ClassPtr2 = ClassPtr1->SomeMethod();\ 
    if (ClassPtr1) && (ClassPtr2)\ 
    {\ 
        try\ 
        {\ 
         //some code 
        }\ 
        catch(...)\ 
        {\ 
         //some code 
        }\ 
    }\ 
    else\ 
        return expression;\ 
    } 
    
+1

您錯過了一些括號。除此之外,你有沒有測試過它?嘗試生成預處理代碼,並查看它。 –

+0

另請注意,必須使用'dynamic_cast' * *可能是不好的設計的標誌。難道不能通過使'SomeMethod'虛擬來解決它嗎? –

+1

順便說一句,當有多個語句並需要宏中的塊時,它通常在'do {...} while(false)'塊(不帶結尾的分號)時通常的模式。 –

回答

3

1:不,您在檢查前使用ClassPtr1,如果它實際爲空,則這是未定義的行爲。你需要先得到ClassPtr1,然後檢查它,然後用它來獲得ClassPtr2,然後檢查。

2:是的,原則上沒問題。這個宏是否是一個好主意是一個不同的問題。

0

1:你可以用C++ 11的關鍵字nullptr檢查。

2:是的,你可以!

+0

這有什麼特別的優勢嗎?你能舉一個例子嗎? – user3207920

+0

它幾乎相同,請檢查:http://stackoverflow.com/questions/11279715/nullptr-and-checking-if-a-pointer-points-to-a-valid-object – hrkz

0

是的,它的工作原理。唯一的問題是你錯過了if必須的括號,所以它不會像擴展後一樣編譯。

此外,您必須在訪問它們之前檢查兩個指針​​,否則您將會收到未定義的行爲,正如@Sebastian Redl指出的那樣。

0
  1. 這不是很正確的語法;那將是if (ClassPtr1 && ClassPtr2)if的條件必須括在括號內)。

  2. 是的,你可以把任意代碼放入宏中。但是通常應該將多語句宏包裝到do { ::: } while (0)構造中,因爲它是唯一包含終止;的宏。所以,你會改變你的宏是這樣的:

    #define MACRO_NAME(object, expression) do { \ 
    /*as before*/ \ 
    } while (0) 
    

沒有這一點,用分號宏,你希望將不屬於以下。試想一下:

if (someCondition) 
    MACRO_NAME(a, b); 
else 
    doStuff(); 

你會得到一個語法錯誤,因爲;宏命令後終止整個if,留下else無法比擬的。


附加說明:您應該檢查ClassPtr1之前取消引用它來獲取ClassPtr2

0

1)是的,如果您修復了括號,並且在檢查它是否爲NULL之前不使用可以爲NULL的指針,那麼可以這樣做。

2)是的,預處理器給出OK代碼。

隨着代碼(有一些修復你讓它編譯):

#include <exception> 
#include <string> 
#define MACRO_NAME(object,expression){\ 
    Class1* ClassPtr1 = dynamic_cast<Class1*>(object);\ 
    Class2* ClassPtr2 = ClassPtr1->SomeMethod();\ 
    if ((ClassPtr1) && (ClassPtr2))\ 
    {\ 
      try\ 
      {\ 
         return expression;\ 
        }\ 
      catch(const std::exception& msg)\ 
      {\ 
         ClassPtr2->SomeOtherMethod(msg.what());\ 
         return 3;\ 
        }\ 
    }\ 
    else\ 
     return expression;\ 
} 

class Class2{public: int SomeOtherMethod(std::string a){return 0;}}; 
class Class1{public: Class2* SomeMethod(){return 0;}}; 
int main() 
{ 
    Class1* a; 
    MACRO_NAME(a,2); 
} 

運行

cpp macro.cpp | tail -7 

將產生

class Class2{public: int SomeOtherMethod(std::string a){return 0;}}; 
class Class1{public: Class2* SomeMethod(){return 0;}}; 
int main() 
{ 
Class1* a; 
{ Class1* ClassPtr1 = dynamic_cast<Class1*>(a); Class2* ClassPtr2 = ClassPtr1->SomeMethod(); if ((ClassPtr1) && (ClassPtr2)) { try { return 2; } catch(const std::exception& msg) { ClassPtr2->SomeOtherMethod(msg.what()); return 3; } } else return 2;}; 
} 
0

與控制結構,如多行宏循環或if/else是可能的。 (後避免;-))爲最佳的做法是在「做{...}而(假)」像這樣包裝的一切:

#define MACRO_NAME(object,expression)\ 
do { if(...) { doSomething; } else { doSomethingElse; } } while(false) 

一個do ... while循環是語法兼容一個單一的陳述,而不是一個正常的塊或一個if ... else。例如,它可以很好地與用戶在其後面寫入的分號搭配使用。你可以,如果使用它..其他:

if(cond) MACRO(); else exit(); 

不會與你的建議bacause萬家樂後面的分號編譯將創建第二個,空語句使「其他」的晃來晃去。不是這樣做的......而是。

0

其實我有兩個問題。 這是「如果(ClassPtr1)& &(ClassPtr2)」正確的方法來檢查它們是否不爲空?

是的,檢查是正確的。宏雖然有一些問題(見下文)。

I want to know if it is possible to include an if else statement completely inside a multi-line macro. I have attached example code. 

是。下面是你的宏的一些問題(以及爲什麼你不應該使用宏來代替函數):

  • 你在檢查它是否爲空之前解引用第一個指針;
  • 該宏看起來像一個函數,但它不會像這樣可用。

考慮這個客戶端代碼:

if(some_condition) 
    MACRO_NAME(MyObject, a+b); 

這個計算結果爲:

if(some_condition) 
    Class1* ClassPtr1 = dynamic_cast<Class1*>(object); 
Class2* ClassPtr2 = ClassPtr1->SomeMethod(); 
// ... 

這是最有可能不是你想要的(如ClassPtr2聲明將發出編譯錯誤 - ClassPtr1是在if塊中本地定義)。

解決方案:

  1. 環繞宏內的代碼do {} while(false)。這將確保宏擴展爲單個代碼塊。這個宏可以工作,但仍然會產生使用宏編寫代碼時固有的所有問題。

  2. 將該宏替換爲引發異常的模板函數(這是正確的解決方案)。作爲一種(非通用)經驗法則,使用宏編寫重複代碼是不完整的API設計的一個症狀(就像使用dynamic_cast是一個糟糕的類層次結構設計的症狀一樣)。