views:

190

answers:

3

Using the following code snippet as an illustration to my question:

// #includes and other macros

class MyClass : public CFormView
{
private:
     DECLARE_DYNCREATE(MyClass)

     bool privateContent;

     ...

public:
     bool publicContent;

     ...
};

class MusicPlayer
{
public:
    AppClass *theApp;       // which has a pointer accessing the MyClass object instantiated in the program

    ...
}

When I place the keyword "private" in MyClass definition as such, the privateContent member variable doesn't appear to be private when I try to access it in a method of MusicPlayer class. However, if I place the "private" keyword after the DECLARE_DYNCREATE(MyClass) line, the behavior of privateContent member variable returns to what is expected. Does anyone know why this is the case? Thanks in advance.

A: 

DECLARE_DYNCREATE is macro that contains public keyword. Actually it contains macro DECLARE_DYNAMIC and there are public keyword.

Kirill V. Lyadvinsky
+7  A: 

If you look at the definition of DECLARE_DYNCREATE, you will see that it uses another macro:

// not serializable, but dynamically constructable
#define DECLARE_DYNCREATE(class_name) \
    DECLARE_DYNAMIC(class_name) \
    static CObject* PASCAL CreateObject();

And if you look at that macro, DECLARE_DYNAMIC, you'll see why your class turns public:

#define DECLARE_DYNAMIC(class_name) \
protected: \
    static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
    static const CRuntimeClass class##class_name; \
    static CRuntimeClass* PASCAL GetThisClass(); \
    virtual CRuntimeClass* GetRuntimeClass() const; \

When it expands, it's going to add that public: keyword, leaving the rest of your class definition public after that.

So when you say say private: after DECLARE_DYNCREATE, you're then changing it from public to private.

The usual use of this macro would be like this:

class MyClass : public CFormView
{
        DECLARE_DYNCREATE(MyClass)
private:
        bool privateContent;

        ...

public:
        bool publicContent;

        ...
};

The class will implicitly be private at the start, so the effect is the same.

Also, most C++ programmers will agree you should start trying to get into the habit of placing your private variables at the bottom.

The justification is that when people, including yourself, are reading the class, they will want to see what you can do with the class, which is in the public interface, rather than how the class is going to work, which is private.

By putting the public interface first, you won't have to be bothered by all the private stuff.

I used to put my private stuff at the top too (because I came from Visual Basic 6, before C++), and hated being told my privates should be on the bottom, but once you get into the habit you'll wish you changed sooner.

GMan
I originally wanted to declare all my contents in MyClass private, hence putting the "private" keyword before DECLARE_DYNCREATE(MyClass) overlooking that it substitutes code snippets including the keyword "public" that makes the rest of my class contents public accessibility.
stanigator
Ah, yea. What MFC does the "usual way" is like my last code snippet, where you put the macro right at the very top, almost like you're trying to ignore it, then program the rest of your class like the macro was never there.
GMan
A: 

I think the DECLARE_DYNCREATE macro must use the public: identifier internally. Why? If you change the above code so that privateContent is declared above the DECLARE_DYNCREATE macro, it has the expected behavior. Thus, I deduce that the macro does a 'public:'. So you again have to declare the appropriate identifier after the macro.

DeusAduro