Объявить глобальную переменную, инициализировать в методе

Я создаю сберегательного клиента, у которого много накладных расходов: TSocket, TBufferedTransport и TBinaryProtocol. Обычно он создается так

Пример сберегательного клиента

int main(int argc, char **argv) {
    shared_ptr<TTransport> mysocket(new TSocket("localhost", 9090));
    shared_ptr<TTransport> mytransport(new TBufferedTransport(mysocket));
    shared_ptr<TProtocol> myprotocol(new TBinaryProtocol(mytransport));
    TestServiceClient client(myprotocol);

    try {
        mytransport->open();
        client.testmethod();  //and you can call server methods like so
        mytransport->close();
    }catch (TException &tx) {
        printf("ERROR: %s\n", tx.what());
    }
}

Однако для моего клиента я хочу, чтобы он был в виде статической библиотеки. Таким образом, нет основного метода, и я создал методы init() и exit() для открытия и закрытия mytransport. Это также означало, что мне нужно было сделать mysocket, mytransport, myprotocol и client все глобальные переменные, но я также хочу установить mysocket на IP, отличный от localhost, что означает инициализацию mysocket внутри метода. Любые идеи?

PS. Кроме того, кто-нибудь знает, как я могу вызывать init() и exit() автоматически, когда статическая библиотека открывается и закрывается? [Решено]

edit: я забыл упомянуть, что я не могу инициализировать mysocket, пока не узнаю правильный ip, поэтому я не думаю, что могу объявить mysocket как глобальную переменную в любом случае


person woojoo666    schedule 16.07.2013    source источник
comment
Вероятно, есть более эффективные способы сделать это, но вы можете использовать статическую локальную переменную. Например, Socket& get(){ static Socket mysocket = initstuff(); return mysocket; }. При первом вызове функции создается и возвращается mysocket. При дальнейших вызовах он просто возвращается.   -  person Suedocode    schedule 17.07.2013
comment
Прочитав правку, я не уверен, что вы все еще ищете другое решение или просто добавляете дополнительную информацию. Если вы не можете выполнить инициализацию до тех пор, пока пользователь не введет что-то, значит, у вас есть точка входа прямо в этой функции ввода.   -  person Suedocode    schedule 18.07.2013


Ответы (2)


Прочитав вопрос более внимательно, я думаю, что это может быть больше похоже на то, что вы ищете:

mylib.h

class libClosure{
  public:
  libClosure();
  ~libClosure();
};

mylib.cpp

#include "mylib.h"
#include <iostream>

using namespace std;

libClosure::libClosure(){ cout << "call open()" << endl;}
libClosure::~libClosure(){ cout << "call close()" << endl;}

libClosure __lc;

main.cpp

#include "mylib.h"
#include <iostream>

using namespace std;

int main(){
  cout << "client.testmethod()" << endl;
  return 0;
}

выход

call open()
client.testmethod()
call close()

Создание инициализирующего объекта в файле реализации - распространенный способ добиться именно того, что вы ищете. По сути, конструктор для class libClosure становится вашей точкой входа, а деструктор для class libClosure становится точкой выхода.

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

person Suedocode    schedule 16.07.2013

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

базовая версия

shared_ptr<TTransport> mysocket(createTSocket());

TSocket* createTSocket() {
    //init stuff goes here, for example
    string ip = "localhost"
    int port = 9090

    return new TSocket(ip,port)
}

полный код (ну, большая его часть)

class ThriftProxy {
public:
    ThriftProxy() :
        trans(createTSocket()),
        proto(new TBinaryProtocol(trans)),
        client(proto)
    {
        trans->open();
    }

    TSocket* createTSocket() {
        //default: ip = "localhost", port = 9090
        string ip = "localhost";
        int port = 9090;

                    //get ip and port from a text file

        return new TSocket(ip, port);
    }

    ~ThriftProxy()
    {
        trans->close();
    }

private:
    boost::shared_ptr<TSocket> trans;
    boost::shared_ptr<TProtocol> proto;
public:
    XtkServiceClient client;
};
person woojoo666    schedule 17.07.2013