2010-03-15 13 views
5

मैं एक कनेक्शन सूचक के चारों ओर एक साधारण रैपर लिखने की कोशिश कर रहा हूं जो रैपर नष्ट होने पर इसे पूल में वापस कर देगा, लेकिन यह संकलित नहीं होगा क्योंकि कनेक्शनपूल और ऑटोकॉन को एक दूसरे की आवश्यकता है घोषित किया जानादो कक्षाएं एक दूसरे से संदर्भित करती हैं

मैंने आगे मंदी का उपयोग करने की कोशिश की लेकिन यह काम नहीं किया। मैं इसे कैसे हल करूं? (छ का उपयोग कर ++) आगे घोषणा

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); 
    } 
}; 
+2

डिज़ाइन के अनुसार यह एक बुरा विचार है, आपको परिपत्र निर्भरता को हटाने का प्रयास करना चाहिए! – NomeN

+0

अच्छी तरह से, यह एक स्थानीय मुद्दा है और कनेक्शन को रिलीज़ करने के बारे में चिंता करने का लाभ (संभावित अपवादों के मुकाबले) इस डिजाइन की समस्या की "बुराई" से कहीं अधिक है। –

+0

http://stackoverflow.com/questions/2233149/two-classes-and-inline-functions –

उत्तर

6

सर्कुलर निर्भरता कार्यों वाले सदस्यों की परिभाषा से आगे की घोषणा और घोषणा के पृथक्करण का एक संयोजन। उदाहरण के लिए:

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); 
} 
+0

महान, अंत में एक असली जवाब :)। धन्यवाद! –

4

उपयोग:

class Connection {}; 

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

class AutoConn { 
//definitions 
}; 

class ConnectionPool { 
//definitions 
}; 
+0

का संभावित डुप्लिकेट मेरा सुझाव है कि आप इसे संकलित करने का प्रयास करें। यह संकलित नहीं करता है। –

0

परिभाषित कर रहे हैं के बाद कार्यों को लागू आप सभी ConnectionPool और AutoConn तरीकों की परिभाषा आउटसोर्स करने के लिए चाहते हो सकता है , यानी

class ConnectionPool; 
class AutoConn {…}; 

class ConnectionPool {…}; 

AutoConn ConnectionPool::getConn() { 
    … 
} 
3

सह एक आगे घोषणा के लिए rrect वाक्य रचना है:

class Connection; // no {} 

आप लिखते हैं तो

class Connection {}; 

तो फिर तुम वर्ग को परिभाषित कर रहे हैं, और आप एक वर्ग में दो बार परिभाषित नहीं कर सकते हैं।

इसके अलावा, क्या आपको AutoConn घोषित नहीं करना चाहिए, Connection नहीं?

+0

यह आगे मंदी नहीं है, यह केवल एक मंदी है इसलिए नमूना संकलित। –

+0

उसने इसे दो बार परिभाषित नहीं किया; यह कनेक्शन की * केवल * परिभाषा है। मुझे लगता है कि पोस्ट कोड की मात्रा को कम करने के लिए यह केवल एक जगह धारक है। – Clifford

+0

ओह, मैंने सोचा था कि आगे की घोषणा में आपका प्रयास था - मेरी माफ़ी। –

0

में ConnectionPool हेडर फ़ाइल शामिल न करें। AutoConn हेडर फ़ाइल में class ConnectionPool; जैसे आगे के संदर्भ का उपयोग करें।

1

आगे की घोषणा केवल संकलक को बताती है "ऐसी कक्षा मौजूद है"। अपने

AutoConn getConn() 

AutoConn के बाद में एक मान प्रकार, AutoConn की पूरी संरचना पता होना चाहिए, ताकि वर्ग के आगे घोषणा से काम नहीं चलेगा है। तो आपको ConnectionPool से पहले AutoConn की वास्तविक घोषणा करना होगा।

आपके 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() { ... } 
+0

यह भी एक सही जवाब है। अच्छे जवाब के लिए +1। –

संबंधित मुद्दे