Използване на const_cast във фабричния модел

Извинете/поправете ме, ако номенклатурата ми е неправилна.

Никога не съм разбирал употребата на const_cast. Най-общо казано, струва ми се, че ако трябва да използвате const_cast, тогава вашият клас/методи вероятно са фундаментално погрешни освен ако не използвате наследени функции, които не са const-правилни. Може обаче да съм попаднал на случай, когато използването му е подходящо. Имам голям клас с няколко членове, които са назначени по време на строителството и остават постоянни за полезния живот на обекта.

Тъй като тези обекти се унищожават и конструират често, бих искал да експериментирам с това, което смятам, че се нарича фабричен модел: вместо да създавам/унищожавам обекта, бих искал да го извлека/върна в кеш от неприсвоени обекти. Например (опростено, разбира се):

class PersonFactory {
public:
    const Person* getPerson(const QString& newname) {
    //I can't assign the new name because it's const
        if(m_personCache.isEmpty())
            return createNewPerson();
        else
            return m_personCache.pop();
    }
    void returnPerson(Person* person) { m_personCache.push(person); person = 0; }
    static PersonFactory* instance;
private:
    Person* createNewPerson() const { return new Person(""); }
    QStack<Person*> m_personCache;
}

class Person {
public:
    friend Person* PersonFactory::createNewPerson();

    const QString& name() const {
        return m_name;
    }

    void destroy() {
        PersonFactory::returnPerson(this);
    }
private:
    Person(QString name) : m_name(name) {}
    //m_name is const and should remain that way to prevent accidental changes
    const QString m_name;
}

Не мога да задам ново име, защото е const. Това добър случай ли е за const_cast или пропускам очевидна алтернатива? Използването на const_cast би ли довело до намаляване на производителността?


person Phlucious    schedule 13.12.2012    source източник
comment
mutable не е знак за дефект в дизайна. Той е там, за да могат обектите например да кешират стойности, вместо да ги преизчисляват всеки път, когато са необходими.   -  person Pete Becker    schedule 14.12.2012
comment
Премахнах препратката към mutable, тъй като не допринесе с нищо за въпроса. Със сигурност има случаи, когато използването му е необходимо.   -  person Phlucious    schedule 14.12.2012
comment
вместо да се занимавате с шаблони за проектиране на Java, обмислете просто използването на C++ разпределител на малки обекти като този в библиотеката Loki. например с подхода на Java не можете да използвате настройките по подразбиране за std::unique_ptr и std::shared_ptr. по този начин има отрицателно въздействие върху коректността и обема на работата   -  person Cheers and hth. - Alf    schedule 14.12.2012


Отговори (1)


Използването на const_cast ще доведе ли до постигане на производителност?

Може би. Прехвърлянето на const за съхраняване на стойност, когато даден обект всъщност е const, води до недефинирано поведение. Недефинираното поведение може да се прояви като, наред с други неща, удар в производителността.

person Pete Becker    schedule 13.12.2012
comment
Прехвърлянето на const за съхраняване на стойност, когато даден обект всъщност е const, води до недефинирано поведение. Можете ли да поясните какво имате предвид под недефинирано поведение? - person Phlucious; 14.12.2012
comment
Имам предвид, че дефиницията на езика не налага никакви изисквания за това какво прави една реализация. Един прост пример, с който се сблъскват много начинаещи, е: int main() { const int i = 3; const_cast<int&>(i) = 4; std::cout << i << '\n'; return 0; } и са изненадани, че програмата извежда 3. Що се отнася до недефинираното поведение, това е доста безобидно. - person Pete Becker; 14.12.2012
comment
Разбрах. Така че използването на фабричния шаблон, както е внедрен, отрича опцията m_name да остане const QString? Предполагам, че мога да го направя не-const, да направя PersonFactory friend class и след това да го присвоя директно. Това ли е правилната ООП техника? - person Phlucious; 14.12.2012
comment
Няма значение. Тази връзка изглежда дава ясен отговор на този въпрос. Този случай на използване на const_cast изглежда фундаментално погрешен. Благодаря! - person Phlucious; 14.12.2012