Domanda

Sto cercando di scrivere un semplice wrapper per un puntatore di connessione che restituirà alla piscina quando l'involucro è distrutto, ma non lo compilo perché il ConnectionPool e AutoConn bisogno l'uno dell'altro per essere dichiarato.

Ho provato ad usare la decelerazione in avanti, ma non ha funzionato. Come lo risolvo? (Usando g ++)

class Connection {};

class ConnectionPool
{
    Connection *m_c;
public: 
    AutoConn getConn()
    {
        return AutoConn(this, m_c); // by value
    }

    void releaseConnection(Connection *c)
    {
    }
};

class AutoConn
{
    ConnectionPool* m_pool;
    Connection *m_connection;
public:
    AutoConn(ConnectionPool* pool, Connection *c) : m_pool(pool), m_connection(c) {}
    ~AutoConn()
    {
        m_pool->releaseConnection(m_connection);
    }
};
È stato utile?

Soluzione

Una combinazione di dichiarazione anticipata e la separazione di dichiarazione definizione dei membri con dipendenze circolari opere. Ad esempio:

class Connection {};
class ConnectionPool ;

class AutoConn
{

    ConnectionPool* m_pool;
    Connection *m_connection;
public:
    AutoConn(ConnectionPool* pool, Connection *c) : m_pool(pool), m_connection(c) {}
    ~AutoConn() ;  // Not defined here because it accesses unknown members of class Connection
} ;

class ConnectionPool
{
    Connection *m_c;
public: 
    AutoConn getConn()
    {
        return AutoConn(this, m_c); // by value
    }

    void releaseConnection(Connection *c)
    {
    }
};

// Definition of destructor with class Connection member dependencies.
AutoConn::~AutoConn()
{
    m_pool->releaseConnection(m_connection);
}

Altri suggerimenti

Usa dichiarazione anticipata:

class Connection {};

class ConnectionPool; //<<<<<<<<<<<<<<<forward declaration

class AutoConn {
//definitions
};

class ConnectionPool {
//definitions
};

implementare le funzioni dopo il punto in cui sono definite le classi

La sintassi corretta per una dichiarazione anticipata è:

class Connection; // no {}

Se si scrive

class Connection {};

Poi si sta definendo la classe, e non si può definire una classe due volte.

Inoltre, non si dovrebbe essere in avanti dichiarando AutoConn, non Connection?

dichiarazione anticipata dice solo al compilatore "quali esiste una classe". Nel vostro

AutoConn getConn()

poiché AutoConn è un tipo di valore, l'intera struttura della AutoConn deve essere nota, dichiarazione così avanti della classe non funzionerà. Quindi è necessario mettere la dichiarazione effettiva di AutoConn prima ConnectionPool.

Nel vostro AutoConn, il tipo ConnectionPool viene indicato solo da puntatori. In questo caso non è richiesto l'intera struttura di ConnectionPool, dichiarazione così in avanti del ConnectionPool è sufficiente.

Pertanto è necessario riarrangiamento le classi in questo modo:

class Connection;
class ConnectionPool;
class AutoConn { ... };
class ConnectionPool { ... };

Ma notare che

AutoConn(ConnectionPool* pool, Connection *c) : m_pool(pool), m_connection(c) {}
~AutoConn()
{
    m_pool->releaseConnection(m_connection);
}

questi metodi richiedono al compilatore di conoscere i membri della ConnectionPool, quindi è necessario una struttura completa. Per risolvere questo problema la definizione deve essere posizionato dopo ConnectionPool. Così solo i costruttori e distruttori dovrebbero rimanere.

class AutoConn {
  ...
  AutoConn(ConnectionPool* pool, Connection *c);
  ~AutoConn();
}
class ConnectionPool { ... };
AutoConn::AutoConn(ConnectionPool* pool, Connection *c) : ... { ... }
AutoConn::~AutoConn() { ... }

Si potrebbe voler esternalizzare la definizione di tutti i metodi e ConnectionPool AutoConn, cioè.

class ConnectionPool;
class AutoConn {…};

class ConnectionPool {…};

AutoConn ConnectionPool::getConn() {
   …
}

Non includere ConnectionPool file di intestazione in AutoConn. Basta usare un riferimento in avanti come class ConnectionPool; nel file di intestazione AutoConn.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top