2012-04-08 5 views
0

Похоже, что преобладающее мнение о том, что использование защищенных данных является плохой идеей. Мне интересно, какая хорошая альтернатива будет в конкретном случае.Альтернативы защищенным членам данных, конкретное тематическое исследование

Возьмем следующий класс под названием CModule, который представляет собой аудиомодуль (музыка трекера в стиле Amiga). Существует много разных форматов модулей, но единственная разница между ними заключается в формате файла (Загрузка) и обработке аудиоэффектов. CModule содержит всю общую функциональность, производные классы реализуют загрузку и эффекты для каждого конкретного формата.

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

Почти все элементы данных защищены, так как функция Load() производного класса должна заполнять их все. Это считается плохим, поскольку он может разрушить инкапсуляцию, если кто-то получает класс из производного класса. Каким будет правильный способ решить эту проблему? Я уже нашел, что использование геттеров/сеттеров тоже считается плохим.

Большого спасибо, кто нашел время, чтобы прочитать это :)

ответ

0

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

Я бы, скорее всего, сделал ваши векторы частными в этом случае, но просто создавал методы получения и установки. Что-то вроде:

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

Это начало только для инструментов, вам также придется придерживаться аналогичного подхода с узорами. В качестве альтернативы вы также можете просто передать вектор, но это немного инкапсулировано.

Также обратите внимание, что я делаю это с верхней части головы и не тестировал его против опечаток, но, надеюсь, он передает идею.