質問

It seems to be the prevailing opinion that using protected data members is a bad idea. I'm wondering what a good alternative would be in a specific case.

Take the following class called CModule, which represents a audio module (Amiga-style tracker music). Many different module formats exist but the only difference between them is in file format (Loading) and audio effects handling. CModule holds all the common functionality, the derived classes implement loading and effects for each specific format.

class CModule
{
public: 
        CModule(string Filename); //Song file name to load.

        //Common methods...
        void Play();
        void Stop(); //Etc...

protected:

        //Derived class should implement these with format specific code.
        //Base class code calls these when needed.
        virtual void Load()=0;
        virtual void Effects()=0;

        //Song information/data.
        vector<CInstrument> Instruments;
        vector<CPattern> Patterns;
        //And much, MUCH more...
};

Almost all the data members are protected since the derived class's Load() function needs to fill them all. This is considered bad since it can break encapsulation if someone derives a class from the derived class. What would be the proper way to solve this problem? I've already found that using getters/setters is considered bad too.

Many thanks to anyone taking the time to read this :)

役に立ちましたか?

解決

There's nothing wrong with using protected data members if using private won't work for your solution, using public data members however is almost never a good idea (however it can be sometimes too).

I would probably make your vectors private in this case but simply create getter and setter methods. Something along the lines of:

class CModule
{
public: 
        CModule(string Filename); //Song file name to load.

        //Common methods...
        void Play();
        void Stop(); //Etc...

protected:

        //Derived class should implement these with format specific code.
        //Base class code calls these when needed.
        virtual void Load()=0;
        virtual void Effects()=0;

        void AddInstrument(CInstrument instrument)
        {
            Instruments.push_back(instrument);
        }

        Instrument GetInstrument(int index)
        {
            return Instruments[index];
        }

        int InstrumentCount()
        {
            return Instruments.size();
        }
private:
        //Song information/data.
        vector<CInstrument> Instruments;
        vector<CPattern> Patterns;
        //And much, MUCH more...
};

This is a start just for instruments, you'll also have to take a similar approach with patterns. Alternatively you could also just pass back the vector but this is a little more encapsulated.

Also note that I am doing this off the top of my head and haven't tested it against typos of whatever but hopefully it conveys the idea.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top