2015-06-22 6 views
13

मेरे पास सी ++ में एक आसान कक्षा है जिसे double या char* के साथ प्रारंभ किया जा सकता है। सब कुछ एक मामले को छोड़कर अपेक्षित काम करता है जब तर्क शून्य होता है।डबल बनाम चार * अस्पष्टता

struct Var { 
    Var (double src) {} 
    Var (char *src) {} 
}; 

int main(int argc, char* argv[]) { 
    Var A = 123; 
    Var B = "abc"; 
    Var C = 0; <- Error: conversion from 'int' to 'Var' is ambiguous 
} 

पहले मैं double के बजाय int इस्तेमाल किया है, और यह किसी कारण के लिए ठीक था।

यह कैसे तय किया जा सकता है?

पुनश्च: मैं जानता हूँ कि मैं (double)0 या सिर्फ 0.0 उपयोग कर सकते हैं, लेकिन वहाँ सिर्फ 0 अनुमति देने के लिए एक मार्ग के रूप डबल स्वीकार करने के लिए है?

+6

क्या आपने एक निर्माता को जोड़ने का प्रयास किया है जो 'int' स्वीकार करता है, जिसे' डबल '-कन्स्ट्रक्टर कहते हैं? – Caramiriel

+2

'सी ++ '' 0' में या तो एक * पूर्णांक शून्य * या * शून्य सूचक * हो सकता है। हाल ही में 'सी ++ 11' मानक पते जो * शून्य सूचक * के लिए कीवर्ड 'nullptr' पेश करके। – Galik

+1

@ गैलिक: क्रमबद्ध करें। यह अभी भी सच है कि '0' संदिग्ध है। –

उत्तर

11

आप किसी तृतीय निर्माता जो double संस्करण के लिए एक int और प्रतिनिधियों लेता जोड़कर अस्पष्टता को समाप्त कर सकता (आवश्यकता सी ++ 11):

struct Var { 
    Var (double src) {} 
    Var (const char *src) {} 
    // ^^^^^ should be const 
    Var (int src) : Var {static_cast<double>(src)} {} 
}; 

बहरहाल, यह अपने char* बदलकर आसान हल किया जा सकता इसके बजाय std::string लेने और प्रत्यक्ष प्रारंभिक उपयोग करने के लिए निर्माता।

+0

अच्छा, कौन जानता है कि 'std :: string' का उपयोग स्वीकार्य है ... पहला विकल्प निश्चित रूप से अच्छा है, अगर ऐसा तरीका हल किया जाना चाहिए। – Deduplicator

7

सी ++ में, शाब्दिक 0 में टाइप int है। कम से कम एक दशमलव बिंदु जोड़ने के बिना, आप इसे पूर्णांक होने के बारे में कुछ भी नहीं बदल सकते हैं। (बिंदु के बाद अंक लिखने के लिए कोई वास्तविक जरूरत है, हालांकि)

आप के बारे में क्यों कॉल 0 साथ 123 साथ स्पष्ट लेकिन अस्पष्ट था निहित सवाल का जवाब करने के लिए:

  • जब आप A प्रारंभ, यह ठीक था, क्योंकि इस मामले में एक इंट से पॉइंटर (char*) में कोई अंतर्निहित रूपांतरण नहीं है।

  • जब आप C किसी पूर्णांक दूसरी बार का उपयोग कर प्रारंभ, आप 0 इस्तेमाल किया, शाब्दिक 0 परोक्ष (, कुछ विरासत व्यवहार से पहले सी ++ 11 nullptr शाब्दिक की पेशकश की) एक सूचक के लिए परिवर्तित किया जा सकता है।

तो, संक्षेप में:

int * a = 0; // legal; 
int * b = 2; // ILLEGAL; 

जब आरंभ C एक रूपांतरण दो उपलब्ध कंस्ट्रक्टर्स के किसी भी (और दोनों रूपांतरण एक ही रैंकिंग है) करने के लिए तर्क देने के लिए की जरूरत है, कॉल अस्पष्ट है।

इसे स्पष्ट बनाने के लिए, आपको या तो अपने शाब्दिक को डबल ((double)0) पर डालना चाहिए, एक डबल शाब्दिक (0.) का उपयोग करें, या एक इंटीरियर लेने वाला एक कन्स्ट्रक्टर जोड़ें। इस अंतिम समाधान के साथ, int लेने वाला कन्स्ट्रक्टर एक सटीक मिलान है, इसलिए यह एक बेहतर मिलान है कि एक और ओवरलोड को रूपांतरण की आवश्यकता होती है (यही कारण है कि इसे चुना जाएगा)।

संपादित करें। कृपया ध्यान दें कि टार्टनलामा उत्तर यहां स्वीकार किया जाना चाहिए क्योंकि यह एक सर्वोत्तम सी ++ अभ्यास है: सी-स्टाइल स्ट्रिंग लेने वाले निर्माता को std::string इसके बजाय लेना चाहिए।चूंकि std::string सी शैली स्ट्रिंग से एक अंतर्निहित रूपांतरण है, कॉल कम परिवर्तन के साथ काम करेंगे:

Var B("abc"); 

लेकिन आप संकेत दिए गए विवरण से अपनी कक्षा इंटरफेस को अलग होगा।

+2

पुन "शाब्दिक 0 प्रकार int int है"। शून्य सूचक के बारे में क्या? और शुद्ध आभासी कार्यों? –

+2

@ पीटर मॉर्टेंसन: शून्य सूचक में एक रूपांतरण शामिल है, इसलिए यह 'int' के प्रत्यक्ष मिलान की तुलना में ओवरलोड रिज़ॉल्यूशन के दौरान खराब हो गया है। शुद्ध आभासी कार्यों के पास शाब्दिक '0' के साथ कुछ लेना देना नहीं है, व्याकरण वहां एक शाब्दिक स्वीकार नहीं करता है, केवल टोकन अनुक्रम' = 0'। (उदाहरण के लिए, '0x0' भी एक पूर्णांक शाब्दिक शून्य है, और यह एक शून्य सूचक में भी परिवर्तित होता है, लेकिन शुद्ध-विनिर्देशक में अस्वीकार्य है) –

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