2009-09-03 28 views
47

मैं निम्नलिखित सी ++ कोड है:अस्पष्ट अधिभार कॉल

#include <math.h> 
#include <cmath.h>  // per http://www.cplusplus.com/reference/clibrary/cmath/abs/ 

// snip ... 

if ((loan_balance < 0) && (abs(loan_balance) > loan_payment)) { 
    ... 
} 

और ऊपर पर make चल रही है:

error: call of overloaded 'abs(double)' is ambiguous 
भी ब्याज की

:

/usr/include/stdlib.h:785: note: candidates are: int abs(int) 

मैं कैसे निर्दिष्ट कर सकता हूं कि कंपाइलर को absath.h में cmath.h में कॉल करने की आवश्यकता है जो फ्लोट को संभाल सकता है?

संकलक की जानकारी (सुनिश्चित नहीं हैं कि अगर यह मायने रखती है):

[[email protected]_box ~/some_code]# gcc -v 
Using built-in specs. 
Target: i386-redhat-linux 
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr /share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=i386-redhat-linux 
Thread model: posix 
gcc version 4.1.2 20080704 (Red Hat 4.1.2-44) 
+6

आपके द्वारा उद्धृत cplusplus पृष्ठ cmath.h शामिल नहीं कहता है। यह cmath कहते हैं। वह math.h का C++ संस्करण है। दोनों शामिल न करें। –

उत्तर

42

हैडर <math.h> एक सी एसटीडी lib हैडर है। यह वैश्विक नामस्थान में बहुत सी चीजें परिभाषित करता है। हेडर <cmath> उस शीर्षलेख का C++ संस्करण है। यह अनिवार्य रूप से नामस्थान std में एक ही सामान को परिभाषित करता है। (कुछ अंतर हैं, जैसे कि सी ++ संस्करण कुछ कार्यों के अधिभार के साथ आता है, लेकिन इससे कोई फर्क नहीं पड़ता।) शीर्षलेख <cmath.h> मौजूद नहीं है।

चूंकि विक्रेता अनिवार्य रूप से एक ही शीर्षलेख के दो संस्करणों को बनाए रखना नहीं चाहते हैं, इसलिए वे दृश्यों के पीछे उनमें से केवल एक को रखने के लिए विभिन्न संभावनाओं के साथ आए। अक्सर, यह सी हेडर है (चूंकि एक सी ++ कंपाइलर उस पर पार्स करने में सक्षम है, जबकि विपरीत काम नहीं करेगा), और सी ++ हेडर में बस इतना शामिल है और सब कुछ नेमस्पेस std में खींचता है। या इसके आसपास लपेटकर namespace std के साथ या उसके बिना एक ही शीर्षलेख को पार्स करने के लिए कुछ मैक्रो जादू है। इसके लिए कुछ वातावरण में यह अजीब है अगर हेडर के पास फ़ाइल एक्सटेंशन नहीं है (जैसे संपादकों कोड को हाइलाइट करने में विफल रहे हैं)। तो कुछ विक्रेताओं के पास <cmath> होगा .h एक्सटेंशन के साथ कुछ अन्य शीर्षलेख सहित एक-लाइनर बनें। या कुछ मानचित्रों में <cblah> से <blah.h> (जो मैक्रो जादू के माध्यम से,परिभाषित किया गया है, और अन्यथा सी हेडर बन जाता है) या <cblah.h> या जो भी हो, मैप करें।

यही कारण है कि <cmath.h> जैसी चीजों सहित कुछ प्लेटफ़ॉर्म पर, जो अस्तित्व में नहीं होना चाहिए, प्रारंभ में सफल होगा, हालांकि यह बाद में संकलक को शानदार रूप से विफल कर सकता है।

मुझे नहीं पता कि आप किस std lib कार्यान्वयन का उपयोग करते हैं। मुझे लगता है कि यह जीसीसी के साथ आता है, लेकिन यह मुझे नहीं पता, इसलिए मैं समझ नहीं सकता कि आपके मामले में क्या हुआ। लेकिन यह निश्चित रूप से उपर्युक्त विक्रेता-विशिष्ट हैक्स में से एक का मिश्रण है और आप एक शीर्षलेख भी शामिल करते हैं जिसमें आपको स्वयं शामिल नहीं करना चाहिए। शायद यह वह जगह है जहां <cmath> नक्शा <cmath.h> पर एक विशिष्ट (सेट) मैक्रो (एस) के साथ हैं जिन्हें आपने परिभाषित नहीं किया था, ताकि आप दोनों परिभाषाओं के साथ समाप्त हो जाएं।

हालांकि, ध्यान दें कि इस कोड को अभी भी चाहिए संकलित करने के लिए नहीं:

#include <cmath> 

double f(double d) 
{ 
    return abs(d); 
} 

वहाँ नहीं ग्लोबल नेम स्पेस (यह std::abs() है) में एक abs() होना चाहिए। हालांकि, उपरोक्त वर्णित कार्यान्वयन चाल के अनुसार, हो सकता है। बाद में इस तरह के कोड को पोर्ट करना (या बस इसे अपने विक्रेता के अगले संस्करण के साथ संकलित करने का प्रयास करना जो इसे अनुमति नहीं देता है) बहुत थकाऊ हो सकता है, इसलिए आपको इस पर नजर रखना चाहिए।

30

इसका उबाल जाता है: math.hC से है और 10 साल पहले बनाया गया था। गणित में, इसकी प्राचीन प्रकृति के कारण, abs() फ़ंक्शन "अनिवार्य रूप से" पूर्णांक प्रकारों के लिए है और यदि आप डबल के पूर्ण मूल्य प्राप्त करना चाहते हैं, तो आपको fabs() का उपयोग करना होगा। जब सी ++ बनाया गया था तो इसे math.h लिया और इसे cmath बनाया। cmath अनिवार्य रूप से math.h है लेकिन सी ++ के लिए बेहतर है। इसने fabs() और abs के बीच अंतर करने जैसी चीजों में सुधार किया, और दोनों युगल और पूर्णांक प्रकारों के लिए abs() बनाया। सारांश में या तो: math.h और उपयोग युगल या उपयोग cmath के लिए पूर्णांकों के लिए abs(), fabs() का उपयोग करें और सब कुछ (आसान और अनुशंसित)

आशा के लिए पेट है इस किसी को भी, जो एक ही समस्या हो रही है मदद करता है!

11

abs() के बजाय fabs() का उपयोग करें, यह वही है लेकिन पूर्णांक के बजाय फ्लोट के लिए है।

+6

जो 'std' नेमस्पेस में वास्तव में सटीक नहीं है, जहां 'फ्लोट',' डबल' आदि के लिए 'abs' अधिभार है – Flexo

+0

निश्चित gcc6 त्रुटि: ओवरलोडेड 'abs (uint32_t)' की कॉल संदिग्ध है –

+0

@ सेरिजियो मुझे लगता है कि आप यूआईटी 32_टी को हस्ताक्षर नहीं किया गया है, क्योंकि सिर्फ कॉल को पेट में हटा देना चाहिए। (इसके बजाय आप fabs (डबल) के लिए डबल करने के लिए uint32_t कास्टिंग कर रहे हैं और फिर मैं परिणाम को पूर्णांक में वापस कास्टिंग मानता हूं!) – Raptor007

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