Компиляция C++, когда два класса относятся друг к другу

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

Я пытался использовать вперед замедление, но оно не работало. Как я решаю это? (использующий 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);
    }
};
5
задан Peter Alexander 15 March 2010 в 13:21
поделиться

7 ответов

Комбинация прямого объявления и отделения объявления от определения членов с круговыми зависимостями работает. Например:

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);
}
6
ответ дан 18 December 2019 в 09:49
поделиться

реализуют функции после точки определения классов

3
ответ дан 18 December 2019 в 09:49
поделиться

Вы можете передать определение всех ConnectionPool и AutoConn методы, то есть

class ConnectionPool;
class AutoConn {…};

class ConnectionPool {…};

AutoConn ConnectionPool::getConn() {
   …
}
0
ответ дан 18 December 2019 в 09:49
поделиться

Прямое объявление только сообщает компилятору, что «такой класс существует».В вашем

AutoConn getConn()

, поскольку AutoConn является типом значения, вся структура AutoConn должна быть известна, поэтому предварительное объявление класса не будет работать. Таким образом, вы должны поместить фактическое объявление AutoConn перед ConnectionPool .

В вашем AutoConn тип ConnectionPool упоминается только указателями. В этом случае вся структура ConnectionPool не требуется, поэтому достаточно прямого объявления ConnectionPool .

Следовательно, вам необходимо переупорядочить классы так:

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

Но обратите внимание, что

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

эти методы требуют, чтобы компилятор знал члены ConnectionPool , поэтому необходима полная структура. Чтобы решить эту проблему, определение необходимо поместить после ConnectionPool . Таким образом, должны остаться только конструкторы и деструкторы.

class AutoConn {
  ...
  AutoConn(ConnectionPool* pool, Connection *c);
  ~AutoConn();
}
class ConnectionPool { ... };
AutoConn::AutoConn(ConnectionPool* pool, Connection *c) : ... { ... }
AutoConn::~AutoConn() { ... }
1
ответ дан 18 December 2019 в 09:49
поделиться

Используйте прямое объявление:

class Connection {};

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

class AutoConn {
//definitions
};

class ConnectionPool {
//definitions
};
4
ответ дан 18 December 2019 в 09:49
поделиться

Не включайте файл заголовка ConnectionPool в AutoConn . Просто используйте прямую ссылку, например class ConnectionPool; в заголовочном файле AutoConn .

0
ответ дан 18 December 2019 в 09:49
поделиться

Правильный синтаксис для прямого объявления таков:

class Connection; // no {}

Если вы пишете

class Connection {};

Тогда вы определяете класс, а вы не можете определить класс дважды.

Также, разве вы не должны объявлять вперед AutoConn, а не Connection?

3
ответ дан 18 December 2019 в 09:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: