2012-05-11 31 views
13

सी ++ प्राइमर पुस्तक के अनुसार, लेखक ने उल्लेख किया है कि हम पूरी कक्षा (पृष्ठ 634) की बजाय किसी अन्य वर्ग के मित्र के रूप में कक्षा सदस्य कार्य निर्दिष्ट कर सकते हैं।किसी वर्ग वर्ग फ़ंक्शन को किसी अन्य श्रेणी के मित्र के रूप में निर्दिष्ट करें?

फिर, मैं इस कोड का परीक्षण किया:

class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 
class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 

मैं सिर्फ अमेरिकन प्लान चाहता था() वर्ग ए का दोस्त है, न कि पूरी क्लास बी होने की लेकिन कोड के बारे में त्रुटि का उत्पादन: 'B' : is not a class or namespace name। (मैं विजुअल सी ++ 2005 का उपयोग कर रहा हूं)

उत्तर

14

ए के पहले बी परिभाषा डालने का प्रयास करें:

class A; // forward declaration of A needed by B 

class B 
{ 
public: 
    // if these require full definition of A, then put body in implementation file 
    void fB(A& a); // Note: no body, unlike original. 
    void fB2(A& a); // no body. 
}; 

class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 

A की जरूरत है B की पूर्ण परिभाषा। हालांकि, B को A के बारे में जानने की आवश्यकता है, लेकिन पूर्ण परिभाषा की आवश्यकता नहीं है, इसलिए आपको A की अगली घोषणा की आवश्यकता है।

+0

लेकिन अगर अमेरिकन प्लान में (ए एंड ए) मैं उदाहरण के लिए एक में चर तक पहुँचने के लिए उपयोग करते हैं, a.variable; यह अवैध होगा क्योंकि ए को अभी तक परिभाषित नहीं किया गया था। – ipkiss

+1

@ipkiss yes, क्योंकि यदि आप हेडर क्लास घोषणा में हैं तो आपको पूर्ण परिभाषा की आवश्यकता होगी। लेकिन अगर आपने इसे एक अलग कार्यान्वयन फ़ाइल में किया है, तो आप ए – juanchopanza

2

इस काम के लिए, B की पूर्ण परिभाषा A की परिभाषा से पहले जानी जानी चाहिए।

तो आगे A घोषित पूर्ण प्रकार की जरूरत नहीं है B के बाद से, और परिभाषाओं के आसपास स्विच:

class A; 
class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 
class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 
0

सबसे पहले कक्षा ए घोषित करें, ताकि कक्षा बी परिभाषा में इसकी दिखाई दे। फिर कक्षा ए को परिभाषित करें जिसमें कक्षा बी

0

किसी विशेष श्रेणी के नाम का उपयोग करने से पहले सबसे पहले आपको इसे पहले घोषित करना होगा। इसलिए आपको क्लास बी की अगली घोषणा की आवश्यकता होगी क्योंकि क्लास बी को मूल रूप से घोषित करने से पहले कक्षा ए में इसका उपयोग कर रहे हैं।

दूसरी कक्षाओं को परिभाषित करने के बाद आपको कार्यों को परिभाषित करने की आवश्यकता होगी (जो दोनों वर्गों से चर का उपयोग कर रहे हैं- यहां मित्र कार्य करता है)। अन्यथा हमें त्रुटियों का सामना करना पड़ सकता है।

उदाहरण

#include<iostream> 

using namespace std; 

class alpha1; 

class alpha2 
{ 
    public: 

     void put_bata(int a,int b); 
}; 

void alpha2 :: put_bata(int a,int b) 
{ 
    alpha1 net; 

    net.roll=a; 

    net.id=b; 

    net.get_data(); 
} 

class alpha1 
{ 
    int roll; 

    int id; 

    public: 

     void get_data(void) 
     { 
      cout<<roll<<endl<<id<<endl; 
     } 

     friend void alpha2 :: put_bata(int a,int b); 
}; 

int main() 
{ 
    alpha2 gamma; 

    gamma.put_bata(5,6); 

    return 0; 
} 

के लिए हमें त्रुटियों ही उन्हें प्रदर्शित करेगा put_bata रोल और आईडी का उपयोग करने के पहले वे परिभाषित कर रहे हैं भले ही हम वर्ग के एक आगे घोषणा लेकिन नीचे दिए गए कोड ठीक काम करेंगे पड़ा कोशिश करता है।

#include<iostream> 

using namespace std; 

class alpha1; 

class alpha2 
{ 
    public: 

     void put_bata(int a,int b); 
}; 

class alpha1 
{ 
    int roll; 

    int id; 

    public: 

     void get_data(void) 
     { 
      cout<<roll<<endl<<id<<endl; 
     } 

     friend void alpha2 :: put_bata(int a,int b); 
}; 

void alpha2 :: put_bata(int a,int b) 
{ 
    alpha1 net; 

    net.roll=a; 

    net.id=b; 

    net.get_data(); 
} 


int main() 
{ 
    alpha2 gamma; 

    gamma.put_bata(5,6); 

    return 0; 
} 
0

@juanchopanza @ipkiss समस्या यह है कि आप एक के अंदर अमेरिकन प्लान के डेटा सदस्यों (ए & क) क्योंकि एक अभी तक परिभाषित नहीं है उपयोग नहीं कर सकते के बारे में। इसे एक अलग फ़ाइल में परिभाषित करने और इसे शामिल करने के बजाय, आप कक्षा ए की परिभाषा के बाद फ़ंक्शन एफबी (ए ए) को परिभाषित कर सकते हैं ताकि एफबी (ए ए) ए

2
के डेटा सदस्यों को देख सके

संकलक (आमतौर पर ऊपर से) कोड को पढ़ने के लिए शुरू होता है और यह इस लाइन का सामना करना पड़ता है:

friend void B::fB(A& a);

फिर संकलक नहीं समझती तो आप इस B:: से क्या मतलब है। भले ही आपने इस कक्षा को कोड में बाद में परिभाषित किया हो लेकिन संकलक इसे नहीं जानता है।तो परिभाषा आमतौर पर कक्षा में रहने के बाद कक्षा (class Name;) की घोषणा करने के लिए अभ्यास करना अच्छा होता है।

2

संकलक कोड (आमतौर पर ऊपर से) संकलन शुरू होता है और यह इस लाइन का सामना करना पड़ता है:

friend void B::fB(A& a); 
    इस बिंदु पर
  1. , संकलक बी के प्रकार की जानकारी के बारे में पता नहीं है तो यह (एक त्रुटि फेंकता 'बी': कक्षा या नामस्थान नाम नहीं है)।
  2. कक्षा बी की आगे की घोषणा द्वारा, कंपाइलर जानता है कि बी के प्रकार सभी सदस्यों के साथ वास्तविक घोषणा के लिए पहले से ही कक्षा है।

  3. वर्ग बी के आगे घोषणा

///////////////

class B; 
class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){}; 
}; 
class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 

फिर भी त्रुटि के बाद नीचे दिए गए कोड रन !!!

क्योंकि आगे की घोषणा सिर्फ एक पहचानकर्ता की घोषणा है जिसके लिए प्रोग्रामर ने अभी तक पूरी परिभाषा नहीं दी है। इसलिए कंपाइलर को कक्षा ए

नोट: कक्षा बी परिभाषाओं को बी के प्रकार पर निर्भर करता है और बी (यानी बी :: एफबी) की परिभाषा भी है ताकि आगे की घोषणा अकेले ही हल नहीं हो सके, कक्षा की पूरी परिभाषा बी वर्ग ए से पहले

4 रन के लिए इस कोड

////////

class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 
class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 

फिर भी त्रुटि को परिभाषित करने की जरूरत है !!!

क्योंकि क्लास B सदस्य कार्यों अमेरिकन प्लान & FB2 ग्रुप ए के तर्कों होने लेकिन संकलक एक तो कक्षा एक से आगे घोषणा के द्वारा, हम संकलक के ए नोट प्रकार की जानकारी के बारे में जानता दे सकते हैं के प्रकार की जानकारी के बारे में पता नहीं है: वर्ग बी परिभाषा केवल एक संकल्प कदम का एक ताकि आगे घोषणा का एक नहीं के सदस्यों के प्रकार पर निर्भर 4.

  1. अंतिम कोड

////// //////////////////

class A; // forward declaration of A needed by B 
class B 
{ 
public: 
    void fB(A& a); 
}; 

class A 
{ 
    int i; 
public: 
    friend void fA(A& a); //specifying function fA as a friend of A, fA is not member function of A 
    friend void B::fB(A& a); //specifying B class member function fB as a friend of A 
}; 

// fA is Friend function of A 
void fA(A& a) 
{ 
    a.i = 11; // accessing and modifying Class A private member i 
    cout<<a.i<<endl; 
} 

// B::fB should be defined after class A definition only because this member function can access Class A members 
void B::fB(A& a) 
{ 
    a.i = 22; // accessing and modifying Class A private member i in Class B member function fB 
    cout<<a.i<<endl; 
} 

int main() 
{ 
    A a; 
    fA(a); // calling friend function of class A 

    B b; 
    b.fB(a); // calling B class member function fB, B:fB is friend of class A 

    return 0; 
} 

6 व्यायाम:

// Cyclic dependency 
#include<iostream> 
using namespace std; 

class A; 

class B 
{ 
public: 
    void fB(A& a); 
    friend void A::fA(B& b); //specifying class A's member function fA as a friend of B 
}; 

class A 
{ 
    int i; 
public: 
    void fA(B& b); 
    friend void B::fB(A& a); //specifying class B's member function fB as a friend of A 
}; 

int main() 
{ 
    return 0; 
} 
+0

की पूर्ण घोषणा शामिल कर सकते हैं तो, आप अभ्यास को कैसे हल करते हैं? –

+0

@ ब्रूनोमार्टिनेज - इसका कोई सही समाधान नहीं है क्योंकि दोनों एक दूसरे की पूर्ण परिभाषा पर चक्रीय रूप से निर्भर हैं। का मेरा इरादा इस विशेष मामले को सॉफ़्टवेयर डिज़ाइन में डीकॉप्लिंग इकाइयों के महत्व को हाइलाइट करना था और इस पर काम करते हुए मित्र कार्य पर अधिक स्पष्टता प्राप्त करना था। मुझे लगता है, आप पहले ही जानते होंगे कि इसके लिए संभावित विकल्प एक आम मित्र फ़ंक्शन बना रहा है – SrinivasPaladugu

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