2009-03-23 13 views
262

मैं वर्गों Foo और Bar इस तरह की स्थापना की है कहते हैं:क्या मैं बेस क्लास के आभासी फ़ंक्शन को कॉल कर सकता हूं यदि मैं इसे ओवरराइड कर रहा हूं?

class Foo 
{ 
public: 
    int x; 

    virtual void printStuff() 
    { 
     std::cout << x << std::endl; 
    } 
}; 

class Bar : public Foo 
{ 
public: 
    int y; 

    void printStuff() 
    { 
     // I would like to call Foo.printStuff() here... 
     std::cout << y << std::endl; 
    } 
}; 

के रूप में कोड में उसकी व्याख्या, मैं आधार वर्ग के समारोह है कि मैं कर रहा हूँ अधिभावी कॉल करने के लिए सक्षम होने के लिए करना चाहते हैं। जावा में super.funcname() वाक्यविन्यास है। क्या यह सी ++ में संभव है?

+1

[बेस क्लास से वर्चुअल फ़ंक्शन कॉल का संभावित डुप्लिकेट] (http://stackoverflow.com/questions/397404/virtual-function-call-from-base-class) –

+1

Googlers के लिए: ध्यान दें कि आपके पास ऐसे मुद्दे हो सकते हैं मैंने इसे कक्षा सदस्य चर के रूप में संग्रहीत करने के साथ किया जो कि सूचक नहीं है। मेरा उत्तर यहां देखें: http: // stackoverflow।कॉम/प्रश्न/47 9 8 9 66/सी-कॉलिंग-पूरी तरह से गलत-वर्चुअल-विधि-ऑफ-ऑब्जेक्ट/42429076 # 42429076 मैंने ठीक करने के लिए नया/हटाया शामिल है। – Andrew

उत्तर

354

सी ++ वाक्य रचना इस तरह है:

class Bar : public Foo { 
    // ... 

    void printStuff() { 
    Foo::printStuff(); // calls base class' function 
    } 
}; 
+8

क्या ऐसा करने के साथ कोई संभावित समस्या है? क्या यह बुरा अभ्यास है? –

+29

@ डेविड: नहीं, यह करने के लिए यह बिल्कुल सामान्य है, हालांकि यह वास्तव में उपयोगी होने पर आपकी वास्तविक कक्षा पर निर्भर हो सकता है। यदि आप ऐसा कुछ करना चाहते हैं तो केवल बेस क्लास विधि को कॉल करें;)। – sth

+11

यह गैर वर्चुअल बेस क्लास विधियों के साथ भी काम करता है। – John

99

हाँ,

class Bar : public Foo 
{ 
    ... 

    void printStuff() 
    { 
     Foo::printStuff(); 
    } 
}; 

यह जावा में super रूप में एक ही है, सिवाय इसके कि यह अलग ठिकानों से कार्यान्वयन बुला आप एकाधिक वंशानुक्रम है जब अनुमति देता है।

class Foo { 
public: 
    virtual void foo() { 
     ... 
    } 
}; 

class Baz { 
public: 
    virtual void foo() { 
     ... 
    } 
}; 

class Bar : public Foo, public Baz { 
public: 
    virtual void foo() { 
     // Choose one, or even call both if you need to. 
     Foo::foo(); 
     Baz::foo(); 
    } 
}; 
+6

यह चयनित एक से बेहतर जवाब है। धन्यवाद। –

26

बस मामले में आप अपनी कक्षा में कार्यों का एक बहुत कुछ के लिए ऐसा करते हैं:

class Foo { 
public: 
    virtual void f1() { 
    // ... 
    } 
    virtual void f2() { 
    // ... 
    } 
    //... 
}; 

class Bar : public Foo { 
private: 
    typedef Foo super; 
public: 
    void f1() { 
    super::f1(); 
    } 
}; 

इस लेखन का एक सा बचत हो सकती है अगर आप फू का नाम बदलना चाहते हैं।

+1

ऐसा करने का मजेदार तरीका है, लेकिन एकाधिक विरासत के साथ काम नहीं करेगा। –

+0

'typedef Foo42 x5metasuper;' – Zyl

+2

और यदि आपके पास 1 से अधिक बेस क्लास है? वैसे भी, यह मूर्खतापूर्ण है और अक्सर किसी अन्य भाषा की तरह दिखने के लिए सी ++ को मोड़ने की कोशिश करने के लिए व्यर्थ। बस बेस का नाम याद रखें और उसे इसके द्वारा कॉल करें। –

61

कभी कभी तुम, आधार वर्ग 'कार्यान्वयन कॉल करने के लिए जब आप व्युत्पन्न समारोह में नहीं हैं की जरूरत है ... यह अभी भी काम करता है:

struct Base 
{ 
    virtual int Foo() 
    { 
     return -1; 
    } 
}; 

struct Derived : public Base 
{ 
    virtual int Foo() 
    { 
     return -2; 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    Base *x = new Derived; 

    ASSERT(-2 == x->Foo()); 

    //syntax is trippy but it works 
    ASSERT(-1 == x->Base::Foo()); 

    return 0; 
} 
6

आप से आधार वर्ग के एक समारोह कॉल करने के लिए चाहते हैं, तो इसके व्युत्पन्न कक्षा आप बस बेस क्लास नाम (जैसे Foo :: printStuff()) के साथ ओवरराइड फ़ंक्शन के अंदर कॉल कर सकते हैं।

कोड यहाँ

#include <iostream> 
using namespace std; 

class Foo 
{ 
public: 
    int x; 

    virtual void printStuff() 
    { 
     cout<<"Base Foo printStuff called"<<endl; 
    } 
}; 

class Bar : public Foo 
{ 
public: 
    int y; 

    void printStuff() 
    { 
     cout<<"derived Bar printStuff called"<<endl; 
     Foo::printStuff();/////also called the base class method 
    } 
}; 

int main() 
{ 
    Bar *b=new Bar; 
    b->printStuff(); 
} 

चला जाता है फिर आप क्रम जो उस वर्ग (व्युत्पन्न या आधार) की वस्तु का उपयोग कर कॉल करने के लिए कार्य करते हैं .लेकिन इस आभासी के रूप में चिह्नित किया जाना चाहिए आधार वर्ग में अपने कार्य की आवश्यकता है पर निर्धारित कर सकते हैं।

कोड नीचे

#include <iostream> 
using namespace std; 

class Foo 
{ 
public: 
    int x; 

    virtual void printStuff() 
    { 
     cout<<"Base Foo printStuff called"<<endl; 
    } 
}; 

class Bar : public Foo 
{ 
public: 
    int y; 

    void printStuff() 
    { 
     cout<<"derived Bar printStuff called"<<endl; 
    } 
}; 

int main() 
{ 

    Foo *foo=new Foo; 
    foo->printStuff();/////this call the base function 
    foo=new Bar; 
    foo->printStuff(); 
} 
0

जांच इस ...

#include <stdio.h> 

class Base { 
public: 
    virtual void gogo(int a) { printf(" Base :: gogo (int) \n"); };  
    virtual void gogo1(int a) { printf(" Base :: gogo1 (int) \n"); }; 
    void gogo2(int a) { printf(" Base :: gogo2 (int) \n"); };  
    void gogo3(int a) { printf(" Base :: gogo3 (int) \n"); }; 
}; 

class Derived : protected Base { 
public: 
    virtual void gogo(int a) { printf(" Derived :: gogo (int) \n"); }; 
    void gogo1(int a) { printf(" Derived :: gogo1 (int) \n"); }; 
    virtual void gogo2(int a) { printf(" Derived :: gogo2 (int) \n"); }; 
    void gogo3(int a) { printf(" Derived :: gogo3 (int) \n"); };  
}; 

int main() { 
    std::cout << "Derived" << std::endl; 
    auto obj = new Derived ; 
    obj->gogo(7); 
    obj->gogo1(7); 
    obj->gogo2(7); 
    obj->gogo3(7); 
    std::cout << "Base" << std::endl; 
    auto base = (Base*)obj; 
    base->gogo(7); 
    base->gogo1(7); 
    base->gogo2(7); 
    base->gogo3(7); 

    std::string s; 
    std::cout << "press any key to exit" << std::endl; 
    std::cin >> s; 
    return 0; 
} 

उत्पादन

Derived 
Derived :: gogo (int) 
Derived :: gogo1 (int) 
Derived :: gogo2 (int) 
Derived :: gogo3 (int) 
Base 
Derived :: gogo (int) 
Derived :: gogo1 (int) 
Base :: gogo2 (int) 
Base :: gogo3 (int) 
press any key to exit 

सबसे अच्छा तरीका है आधार उपयोग कर रहा है :: समारोह के रूप में कहते हैं कि @sth

0

हां आप इसे कॉल कर सकते हैं। बच्चे कक्षा में माता पिता के वर्ग समारोह फोन करने के लिए सी ++ वाक्य रचना

class child: public parent { 
    // ... 

    void methodName() { 
    parent::methodName(); // calls Parent class' function 
    } 
}; 

समारोह overriding बारे में अधिक पढ़ें है।

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