2010-09-23 2 views
0

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

Вот класс:

class Foo { 
    typedef std::map<int,double> VecElem; 
    std::vector<VecElem> vec_; 
public: 
    void Insert(std::size_t index0, int index1, double d); 
    // ... other essential functions 
}; 

void Foo::Insert(std::size_t index0, int index1, double d) { 
    vec_[index0][index1] = d; 
} 

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

void MapIndex1(const std::map<std::size_t,std::size_t>& old_to_new); 

Учитывая то, как Foo в настоящее время хранит свои элементы это означает полную перестройку внутренних данных, но это не должно подвергаться пользователю. Но и это не должно быть функцией-членом.

Это типичный случай функции, не входящей в функцию friend? Есть ли другие возможности? Мне не очень нравится концепция функции non-member , потому что эта странная функция (которая может быть только временно необходима в качестве обходного пути для некоторой проблемы) все равно должна быть упомянута внутри «официального» класса (т.е. должен никогда не меняться). Но я думаю, я не могу обойти это?

+3

Я бы не стал слишком беспокоиться о добавлении/удалении друга. Правило, что «официальное» тело класса никогда не должно меняться, вдохновлено тем, что интерфейс вашего класса никогда не должен меняться. Вы хотите временно изменить интерфейс, как взломать (хотя и только интерфейс через некоторую недокументированную функцию друга). Если это оправдано, то изменение тела класса оправдано. Если это не оправдано, тогда не планируйте временный взлом вообще: исправьте его правильно ... –

ответ

-1

Идея для борьбы с этим сценарием является добавление функции, как:

void Ioctl(int func, void* params); к классу. Затем эту функцию можно использовать в качестве шлюзов для всех этих временных сценариев хакки по мере их возникновения. Затем их можно безопасно удалить, когда требование исчезнет без нарушения совместимости (если, конечно, кто-то неофициально их не использует).

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

Внутренне вы можете определить определенные целочисленные значения func для вызова функции и присвоить значение params всем, что вам нужно.

+1

Как это отличается от добавления методов, кроме потери безопасности типа? Вы просто переоцениваете механизм метода самостоятельно. Как вы сами упоминаете, вы все еще полагаетесь на то, что пользователи не используют функциональность. –

0

Как насчет публичного вложенного класса для выполнения работы? Тогда у него может быть функция MapIndex1, которая автоматически получает доступ к закрытым членам закрывающего класса. Когда вы закончите, просто удалите вложенный класс.

class Foo { 
// ... 
public: 
    void Insert(std::size_t index0, int index1, double d); 
    // ... other essential functions 
    class Remapper 
    { 
    public: 
    Remapper(Foo& foo) : foo_(foo) { } 
    void MapIndex1(const std::map<std::size_t,std::size_t>& old_to_new); 
    private: 
    Foo& foo_; 
    }; 
}; 

Foo myFoo; 
Foo::Remapper remapper(myFoo); 
remapper.MapIndex1(...); 
+0

Я бы сделал конструктор копирования и скопировал назначение 'Foo :: Remapper' private, чтобы уменьшить вероятность неправильного использования. – aschepler

Смежные вопросы