簡體   English   中英

C ++編寫類似函數的宏

[英]C++ writing a proper function-like macro

我一直在努力嘗試編寫一個像#define函數一樣的宏,但被卡住了。 這是我正在使用的示例:

#include <iostream>
#define pMAKE(x,y,z,dest)\
    (dest).(x) = (x);\
    (dest).(y) = (y);\
    (dest).(z) = (z);

struct pt {
    double x, y, z;
};

int main() {
    pt p;
    pMAKE(0,1,2,p);
    return 0;
}

我得到的錯誤:

A.cpp: In function ‘int main()’:
A.cpp:13: error: expected unqualified-id before ‘(’ token
A.cpp:13: error: expected unqualified-id before ‘(’ token
A.cpp:13: error: expected unqualified-id before ‘(’ token

錯誤是什么意思,為什么我會得到它們? 我設法使以下人員按自己想要的方式工作,但是老實說我很幸運,我真的不明白發生了什么。

#define pMAKE(X,Y,Z,dest)\
    dest.x = (X);\
    dest.y = (Y);\
    dest.z = (Z);

我非常感謝您的幫助!

對於您的宏的第一個版本, pMAKE(0,1,2,p); 擴展到

p.0 = 0;
p.1 = 1;
p.2 = 2;;

換句話說,您已經通過使用xyz作為變量名(在分配的左側)和標簽來替換了對ptxyz成員的引用,這些標簽將被pre-處理器(在分配的右側)。

(正如Konrad Rudolph指出的那樣),不幸的是,您的宏還有另一個嚴重的錯誤。 考慮以下形式的代碼

pt p;
if (foo)
    pMAKE(0,1,2,p);

擴展到

pt p;
if (foo)
    p.x = 0;
p.y = 1;  // happens regardless of 'foo' test
p.z = 2;; // happens regardless of 'foo' test

您可以通過將宏更改為來解決此問題(並消除煩人的多余分號)

#define pMAKE(X,Y,Z,dest)\
    do { \
        (dest).x = (X);\
        (dest).y = (Y);\
        (dest).z = (Z);\
    } while (0)
struct pt {
    double x, y, z;
    pt(double _x, double _y, double _z) : x(_x), y(_y), z(_z) { }
};

pt p (0.0, 1.0, 2.0);

不要在C ++中使用宏。

或者,就像@potatoswatter建議的那樣,立即 在C ++ 11中 完成它

struct pt { double x, y, z; };
pt p = { 0.0, 1.0, 2.0 };

錯誤是什么意思,為什么我會得到它們?

宏將所有出現的參數替換為參數; 所以

(dest).(x) = (x)

變成

(dest).(0) = (0)

廢話 編譯器需要一個成員名稱(一個標識符,該標識符在語言語法中稱為“ unqualified-id”),但改為看到(0)

在第二個版本中, x不是參數名稱,因此dest.x不會更改。

更好的方法是避免使用宏。 使用功能:

pt make_pt(double x, double y, double z) {
    pt p;
    p.x = x; 
    p.y = y;
    p.z = z;
    return p;
}

int main() {
    pt p = make_pt(0,1,2);
}

或者只使用聚合初始化:

int main() {
    pt p = {0,1,2};
}

並且在C ++ 11中,從初始化程序列表進行賦值:

p = {4,5,6};

宏用作文本替換。 宏的參數出現在替換列表中的任何地方,都將在文本上替換為參數。 因此,在您的情況下, pMAKE(0, 1, 2, p); 擴展為:

(p).(0) = (0);
(p).(1) = (1);
(p).(2) = (2);;

(實際上,由於宏不保留換行符,因此將全部放在一行上,但是為了清楚起見,我將其放在三行上)。

在您的情況下,您不需要宏。 您需要一個內聯函數(可能是pt的成員函數或構造函數)。 僅在需要文本性質的地方使用宏(例如,將標記合並為標識符等)。 對於其他所有功能,請使用(內聯)函數。 像這樣:

struct pt
{
  double x, y, z;
  pt(double ax, double ay, double az) : x(ax), y(ay), z(az) {}
};

int main()
{
  pt p(0, 1, 2);
}

使用內聯函數

pt& pMake(int x, int y, int z, pt&p){
    p.x=x;
    p.y=y;
    p.z=z;
    return p;
};

.(x)成員訪問不小心使用了參數x的名稱。 (此外,成員訪問的第二個操作數也不是表達式,因此不屬於括號。)最佳做法是將所有宏名稱和宏參數都保留在所有大寫形式中,以防止命名沖突。 並避免使用單個字符標識符。

#define POINT_MAKE(X,Y,Z,DEST)\
    (DEST).x = (X);\
    (DEST).y = (Y);\
    (DEST).z = (Z);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM