2010-09-29 10 views
5

मेरे पास एक साधारण सी ++ बेस क्लास है, व्युत्पन्न क्लास उदाहरण है।सी ++ विरासत, आधार विधियों को छिपा

// Base.hpp 
#pragma once 

class Base 
{ 
public: 
    virtual float getData(); 
    virtual void setData(float a, float b); 
    virtual void setData(float d); 

protected: 
    float data; 
}; 

//Base.cpp 
#include "stdafx.h" 
#include "Base.hpp" 

float Base::getData() 
{ 
    return data; 
} 

void Base::setData(float a, float b) 
{ 
    setData(a); 
} 

void Base::setData(float d) 
{ 
    data = d; 
} 

//Derived.hpp 
#pragma once 
#include "Base.hpp" 

class Derived 
    : public Base 
{ 
public: 
    virtual void setData(float d); 
}; 

//Derived.cpp 
#include "stdafx.h" 
#include "Derived.hpp" 

void Derived::setData(float d) 
{ 
    data = d + 10.0f; 
} 

यदि अब मैं आधार पर एक सूचक बना देता हूं तो यह ठीक से संकलित होता है।

//Main.cpp 
#include "stdafx.h" 
#include "Base.hpp" 
#include "Derived.hpp" 

Base *obj = new Derived(); 

लेकिन अगर मैं व्युत्पन्न वर्ग के लिए एक सूचक है, तो संकलक (वीसी 2008 और 2010) बनाने शिकायत है कि:

Main.cpp(12): error C2660: 'Derived::setData' : function does not take 2 arguments 

और यहाँ कोड है कि इस त्रुटि का कारण बनता है:

//Main.cpp 
#include "stdafx.h" 
#include "Base.hpp" 
#include "Derived.hpp" 

Derived *obj = new Derived(); 

ऐसा लगता है कि बेस क्लास विधियों को छुपाया जा रहा है। मैं इस धारणा के तहत था कि बेस क्लास विधियों वर्चुअल हैं क्योंकि वे व्युत्पन्न सूचक से देखे जाने पर भी दिखाई दे सकते हैं, या क्या मैं गलत हूं?

+0

आपकी व्युत्पन्न कक्षा कैसी दिखती है? –

+1

संभावित डुप्लिकेट [सी ++ में बेस के अधिभारित फ़ंक्शन को ओवरराइड करना] (http://stackoverflow.com/questions/888235/overriding-a-bases-overloaded-function-in-c) –

उत्तर

11

यह सी ++ नाम लुकअप का एक आर्टिफैक्ट है। मूल एल्गोरिदम यह है कि संकलक वर्तमान मान के प्रकार से शुरू होगा और पदानुक्रम तक आगे बढ़ेगा जब तक कि उस प्रकार के सदस्य को लक्ष्य नाम न हो। इसके बाद दिए गए नाम के साथ उस प्रकार के सदस्यों पर केवल ओवरलोड रिज़ॉल्यूशन होगा। यह मूल नामों पर एक ही नाम के सदस्यों पर विचार नहीं करता है।

तरह से इससे बचने के लिए Derived पर कार्यों को फिर से परिभाषित करने के लिए और सिर्फ उन्हें आगे अप Base

class Derived { 
    ... 
    void setData(float a, float b); 
} 

void Derived::setData(float a, float b) { 
    Base::setData(a,b); 
} 

के साथ ही आप using घोषणा

class Derived { 
    using Base::setData; 
    ... 
} 
का उपयोग कर दायरे में आधार सदस्यों ला सकता है

+1

शायद आप 'उपयोग करने के लिए संकेत जोड़ सकते हैं '? – sbi

+0

@ एसबीआई, अच्छी कॉल। जोड़ा गया – JaredPar

+0

@ जेरी, धन्यवाद – JaredPar

3

व्युत्पन्न कक्षा में एक फ़ंक्शन बेस क्लास में उसी नाम के किसी भी फ़ंक्शन को छुपाएगा।

तुम सच में आधार वर्ग समारोह (रों) उस नाम का दिखाई देना चाहते हैं, तो आप इसे ऐसा करने के लिए एक घोषणा का उपयोग कर जोड़ सकते हैं:

class Base { 
public: 
    void setData(float d); 
    void setData(float d, float e); 
}; 

class Derived : public Base { 

    using Base::setData; 

    void SetData(float d); 
}; 

[संशोधित:] लगता है मेरी स्मृति गलत था। यह अस्पष्टता का कारण नहीं बनता है - यहां तक ​​कि उपयोग की घोषणा के साथ, Derived::setData प्राथमिकता लेता है (इसलिए बोलने के लिए) ताकि जब आप व्युत्पन्न ऑब्जेक्ट पर setData(float) का आह्वान करते हैं, तो आपको Derived::setData(float) मिलता है। यदि आप वर्चुअल बनाते हैं और आधार पर पॉइंटर के माध्यम से आवेदक करते हैं, तो आपको अभी भी Derived::setData(float); मिलते हैं।

+0

हाँ, यह मेरे रास्ते से '+ 1' जाने का तरीका है (हालांकि जेरेड ने कारणों को और अधिक अच्छी तरह से समझाया)। – sbi

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