如何定义一个在调用后保留其范围的宏

时间:2010-04-19 15:34:43

标签: variables visual-c++ scope c++-cli c-preprocessor

我正在尝试制作一个宏,以便更容易定义属性。

简化示例,但目前我要提供一个带有公共get和私有集的属性:

#define propertyRO(xxType, xxName)\
    property xxType xxName\
    {\
        xxType get() {return m___##xxName;}\
        void set(xxType value) {m___##xxName = value;}\
    }\
    private:\
        xxType m___##xxName;\

然后使用它你会这样做:

public ref class Wawawa
{
public:
    int bob;
    propertyRO(String^, MyName);
};

这可能会很好用,但它有缺陷,因为成员是在私有范围内指定的,这意味着在宏也获得私有范围之后发生的任何事情。 e.g:

public ref class Wawawa
{
public:
    int bob;
    propertyRO(String^, MyName);
    int fred; //ERROR HERE <- this would be private not public
};

因此,如果你忽略了这个宏实际上做了什么,我真正的问题是:有没有办法在宏中使用private:关键字,而不影响其他类?

4 个答案:

答案 0 :(得分:2)

在类定义的末尾将所有属性宏调用一起插入。 (我同意,这个答案有点蹩脚;))

答案 1 :(得分:2)

我会回答:就是不要这样做。不要使用宏来生成代码。它看起来会节省您的时间和精力,但您已经发现宏存在问题,对于阅读类声明的人来说,这当然不明显。您可能很快就会发现调试它是一场噩梦,因为调试器只指向宏行,而不是指向其中的代码。

IMO,咬紧牙关,然后全部写出所有属性。

答案 2 :(得分:2)

我觉得这是不可能的。

所以也许更好的建议是将宏重命名为publicPropertyRO,这将显然会创建一个公共属性。并将私有成员移动到属性声明之上:

#define publicPropertyRO(xxType, xxName)\
    private:\
        xxType m___##xxName;\
    public:\
        property xxType xxName\
        {\
            xxType get() {return m___##xxName;}\
            void set(xxType value) {m___##xxName = value;}\
        }\

这会让班级处于public:状态,我认为这是可以接受的 没有真正回答我的问题,但至少它是一个改进。

答案 3 :(得分:2)

问题的核心是propertyRO宏改变了引擎盖范围,对吧?问题不在于它本身会改变范围,而是以隐藏的方式完成,因此处理此问题的最佳方法是公开它。

Demoncodemonkey's suggestion是将public嵌入到函数的名称中(可能没问题),但另一种方法是使宏后面的作用域成为参数。 E.g。

#define propertyRO(xxType, xxName, xxFollowingScope)\
    property xxType xxName\
    {\
        xxType get() {return m___##xxName;}\
        void set(xxType value) {m___##xxName = value;}\
    }\
    private:\
        xxType m___##xxName;\
    xxFollowingScope:

...

public ref class Wawawa
{
public:
    int bob;
    propertyRO(String^, MyName, public);
    int fred; // No error here, fred is public
};

语法和命名不是很好,但是它确保在没有有意识地确定函数后范围应该是什么的情况下不可能使用这个宏。