2009-08-28 4 views
0

У меня есть класс, который выполняет протокол MSNP15. Протокол требует от клиентов частое подключение/отключение к различным серверам, таким как сервер отправки, сервер входа и сервер коммутатора.Проблема проектирования класса C++

я решил хранить переменные протокола по связанных (например, жетонов билетов, Nonce и т.д.) в качестве статических переменных-членов в полезности класса, как показано ниже:

class MsnUtility 
    { 
    public: 
     static void SetChallengeStringL (const char *string); 

     static const char* GetChallengeString (); 

     static void SetContactTicketL (const char *ticket); 

     static const char* GetContactTicket (); 

    private: 

     MsnUtility(); 

    static char *iChallengeString; 

     static char *iContactTicket; 
    }; 

Статические переменные выше инициализируется NULL при запуске, а затем когда токены становятся доступными по мере выполнения протокола.

Поскольку у меня нет доступа к стандартной библиотеке C++ (поскольку я разрабатываю платформу Symbian S60), я не могу использовать библиотеку строк. Выделите выделенные указатели символов, когда программа выйдет или есть какой-либо другой механизм, благодаря которому я мог бы обеспечить их освобождение.

Я также открыт для альтернативных предложений по дизайну.

+0

Почему бы вам не пойти дальше и написать небольшой класс строк? Не нужно быть умным, просто простой был бы лучше, чем голые указатели. Выберите любую из более старых, но хороших книг на C++, если вы не посмеете. Написание классов строк однажды было очень популярным спортом в помещении для программистов на С ++ и должно быть описано в любой достойной текстовой книге, достаточно старой, чтобы предшествовать std lib. Если вы больше не начинаете C++, это не займет больше дня или дня. – sbi

ответ

1

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

Я думаю, что лучшей идеей в этом случае было бы иметь одноэлементный класс со всеми необходимыми токенами. Сделайте этот класс доступным по всему миру, предоставите необходимые сеттеры \ getters для манипуляции с токеном. Затем, когда dtor одноэлементного класса вызывается при выходе из программы, вы можете де-alllocate память.

Что-то на следующих линиях: -

class TokenDict { 
public: 
    static TokenDict& instance() { 
    static TokenDict instance; 
    return instance; 
    } 
    // getters \ setters for tokens 
    void setToken(char* tptr) { 
    if(token1) 
     delete[] token1; 
    // allocate memory for new token here 
    token1 = new char[strlen(tptr) + 1]; 
    // copy tptr into token1 
    } 
    char const* getToken() const { return token1; } 
private: 
    ~TokenDict() 
    { 
    delete[] token1; 
    } 
    TokenDict() : token1(0) // ctor hidden 
    { } 
    TokenDict(TokenDict const&); // copy ctor hidden 
    TokenDict& operator=(TokenDict const&); // assign op. hidden 
    char* token1; 
}; 
+0

Каким образом это «дикт»? Я вижу только оболочку для одного массива символов. И почему публичный деструктор? – Ropez

+0

@ Ropez: Хмм хороший улов. Дтор можно сделать частным. На днях набрал сразу. Abt the 'dict', ну, это был всего лишь намек на то, чтобы обернуть маркеры либо в виде интерфейса карты, либо сделать их отдельными токенами. Если нужна функция поиска, маркеры могут содержаться в наборе , где CStrCmp является настраиваемым компаратором для char *. – Abhay

0

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

+1

Обратите внимание, что * большинство * платформ будут восстанавливать память приложения, но это не заданный. Если я правильно помню, Win98 этого не сделал. Для Symbian OS, проверьте: http://discussion.forum.nokia.com/forum/showthread.php?t=149695 – outis

+0

Тогда в этом случае идите для второго решения «singleton с подсчетом ссылок». :-) – Learner

+0

Не могли бы вы объяснить «синглтон с подсчетом ссылок»? Количество ссылок на что? Независимо от того, исправлена ​​ли память или нет, выход программы не является проблемой, правильный дизайн класса MsnUtility. –

0

Если вы собираетесь использовать несколько экземпляров класса MsnUtility Пожалуйста, обратите внимание, что, как некоторые из его поля статичны - в основном все экземпляры этого будет быть одинаковым. Это называется Синглтон - и, вероятно, это не то, что вы делали.

+0

Maciek: Мне не нужны несколько экземпляров MsnUtility. Просто один экземпляр, содержащий все необходимые протокольные переменные и связанные с ними методы setter/getter. – ardsrk

1

Зачем нужен класс, если все переменные являются статическими? Если вы хотите только один экземпляр класса, подумайте о том, чтобы сделать его одиночным. Затем вы можете использовать конструктор и деструктор для управления памятью. Я заново спроектировал класс как одноточечная:

class MsnUtility 
{ 
public: 
    static MsnUtility& Instance() 
    { 
    return instance; 
    } 
public: 
    void SetChallengeStringL(const char* cstring) 
    { 
    if (iChallengeString) delete[] iChallengeString; 
    iChallengeString = new char[strlen(cstring) + 1]; 
    strcpy(iChallengeString, cstring); 
    } 
    const char* GetChallengeString() const 
    { 
    return iChallengeString; 
    } 
    void SetContactTicketL(const char* ticket) 
    { 
    if (iContactTicket) delete[] iContactTicket; 
    iContactTicket = new char[strlen(ticket) + 1]; 
    strcpy(iContactTicket, ticket); 
    } 
    const char* GetContactTicket() const 
    { 
    return iContactTicket; 
    } 
private: 
    MsnUtility() : iChallengeString(0), iContactTicket(0) { } 
    ~MsnUtility() 
    { 
    if (iChallengeString) delete[] iChallengeString; 
    if (iContactTicket) delete[] iContactTicket; 
    } 
    char* iChallengeString; 
    char* iContactTicket; 
    static MsnUtility instance; 
}; 

Вы можете использовать класс вроде этого:

// test.cpp 

#include <iostream> // or whatever is available on your development platform. 
#include "MsnUtility.h" 

MsnUtility MsnUtility::instance; 

int 
main() 
{ 
    MsnUtility& u = MsnUtility::Instance(); 
    u.SetContactTicketL("ticket"); 
    u.SetChallengeStringL("ch"); 
    std::cout << u.GetContactTicket() << ", " << u.GetChallengeString() << '\n'; 
    return 0; 
} 
+0

Vijay, должен ли экземпляр быть статической переменной класса? Каковы недостатки, если я создаю локальную статическую переменную и объявляю ее в методе MsnUtility :: Instance(), как предлагает Абхай. – ardsrk

+0

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

+1

@Vijay: Я не согласен. Другие функции-члены могут, вероятно, использовать instance() без накладных расходов на системный вызов, потому что компилятор будет встроить эту функцию. Но что более важно, другие функции-члены должны использовать «это» вместо этого. – Ropez

0

Я думаю, вы можете посмотреть в Qt Tower проект, он еще находится на ранних стадиях, но у него есть библиотека богатого класса, которая также включает интерфейс.

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