Как определить макрос, который сохраняет свою область видимости после вызова - PullRequest
2 голосов
/ 19 апреля 2010

Я пытаюсь создать макрос, чтобы упростить определение свойств.

Упрощенный пример, но на данный момент у меня есть это, чтобы предоставить свойство с публичным набором get и private:

#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);
};

Это потенциально могло бы работать отлично, но оно некорректно, потому что член указан в частной области, что означает, что все, что происходит после того, как макрос также получает частную область. например:

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

Итак, если вы игнорируете, что на самом деле делает этот макрос, мой реальный вопрос: есть ли способ использовать ключевое слово private: в макросе, не затрагивая остальную часть класса?

Ответы [ 4 ]

2 голосов
/ 28 февраля 2011

Суть проблемы в том, что макрос propertyRO меняет область видимости под капотом, верно? Проблема не в том, что он меняет область видимости как таковую, а в том, что это делается скрытно, поэтому лучший способ справиться с этим - это раскрыть его.

Предложение Demoncodemonkey состоит в том, чтобы вставлять public в имя функции (что может быть в порядке), но альтернативой является сделать область видимости после макроса параметром. Э.Г.

#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
};

Синтаксис и наименование не очень хороши, но он гарантирует, что невозможно использовать этот макрос без сознательного принятия решения о том, какой должна быть область действия после функции.

2 голосов
/ 19 апреля 2010

Я бы ответил: просто не делай этого. Не используйте макросы для генерации кода. Похоже, это сэкономит ваше время и усилия, но вы уже обнаружили, что у макроса есть проблема, которая, конечно, не очевидна для тех, кто читает объявление класса. Вы также можете вскоре обнаружить, что отладка - это кошмар, так как отладчик просто указывает на строку макроса, а не код внутри нее.

ИМО, прикуси пулю и просто запиши все свойства полностью.

2 голосов
/ 19 апреля 2010

У меня такое ощущение, что это невозможно.

Так что, возможно, лучшим предложением было бы переименовать макрос в 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:, что я считаю приемлемым.
Не совсем ответил на мой вопрос, но, по крайней мере, это улучшение.

2 голосов
/ 19 апреля 2010

Вставьте все вызовы макроса свойств все вместе в конце определения класса. (И я согласен, что этот ответ отчасти хромает;))

...