2011-08-06 15 views
8

मैं एक फ़ाइल "SimpleFunctions.h" कहा जाता है इस प्रकार परिभाषित किया गया है:समारोह पहले से ही सी में त्रुटि परिभाषित ++

#ifndef SIMPLEFUNCTIONS_H 
#define SIMPLEFUNCTIONS_H 

namespace my_namespace { 

double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); } 
float round(float r) { return round((double)r); } 

} 

#endif // SIMPLEFUNCTIONS_H 

इस फ़ाइल में पहले से ही एक फ़ाइल में शामिल किया गया था और यह ठीक काम कर रहा था।

अब आज मैंने इसे दूसरी फ़ाइल में शामिल किया है और यह अब काम नहीं करता है। लिंक समय पर, यह मुझे बताता है कि फ़ंक्शन पहले से ही "firstfile.obj" में परिभाषित है।

हालांकि, चूंकि मैं उपयोग कर रहा हूं गार्ड शामिल हैं, मैं उम्मीद करता हूं कि कार्यों को केवल एक बार परिभाषित किया जाए, या क्या मुझे कुछ याद आ रहा है?

उत्तर

17

डिफ़ॉल्ट रूप से, इन कार्यों में बाहरी संबंध होता है। इसका मतलब है कि प्रत्येक अनुवाद इकाई में डबल राउंड (डबल आर) और फ्लोट राउंड (फ्लोट आर) नामक फ़ंक्शन होते हैं, जो लिंक समय पर नाम टक्कर का कारण बनते हैं।

कुछ संभव समाधान हैं:

  1. स्थिर है, जो आंतरिक संबंध
  2. इनलाइन कार्यों का तात्पर्य
  3. हैडर से बाहर है और एसी में कार्यान्वयन ले जाएँ/C++ फाइल के रूप में कार्य घोषित

यहां और पढ़ें: What is external linkage and internal linkage?

वैसे, गार्ड एक हेडर फ़ाइल को कई बार शामिल करने से एकल अनुवाद इकाई की रक्षा करते हैं। यह एक अलग मुद्दा है कि आप यहां क्या देख रहे हैं।

+0

आप सही हैं। यही कारण है कि आपको हेडर के अंदर कार्यों को कार्यान्वित करने से बचना चाहिए। –

+0

'इनलाइन' _not_ को अंतराल संबंध का संकेत देता है। http://stackoverflow.com/questions/4957582/how-can-i-prove-that-inline-functions-default-to-internal-linkage –

+0

@ चार्ल्स: मेरी गलती - मैंने जवाब संपादित किया है – pepsi

2

उपयोग 'इनलाइन'

inline double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); } 
inline float round(float r) { return round((double)r); } 

संकलक जरूरी कोड इनलाइन नहीं होगा (हालांकि यह हो सकता है समारोह इस छोटे के लिए), लेकिन लिंकर का इलाज नहीं है अब और एक अलग समारोह के रूप में है।

नोट - शामिल गार्ड को रोकने के एक ही फाइल में शामिल एक बार में एक ही स्रोत फ़ाइल की तुलना में अधिक शामिल किया जा रहा (सख्ती से बोला 'संकलन इकाई') इसे रोकने नहीं है कि यह अलग स्रोत फ़ाइलें है कि एक साथ जुड़े हुए हैं में भी शामिल किया। यही कारण है कि आप इसे सामान्य रूप से एक शीर्षलेख में घोषित करते हैं लेकिन एक फ़ाइल में फ़ाइल को परिभाषित करते हैं

+0

यह काम किया, धन्यवाद। हालांकि मैं उत्सुक हूं - कंपाइलर में फाइल को दो बार शामिल क्यों किया गया है, भले ही इसमें एक गार्ड शामिल है? –

+0

मैं भी जानना चाहता हूं! :) – Casey

+1

यह एक अलग अनुवाद इकाई है - मैक्रो परिभाषा अनुवाद इकाइयों (कंपाइलर आमंत्रण) नहीं फैलती है। लिंकर में अब दौर की 2 परिभाषाएं हैं, और त्रुटियां हैं। इस मुद्दे को हल करने के लिए 'स्थिर 'भी सही है। –

1

समस्या को हल करने का एक बेहतर तरीका टेम्पलेट्स के माध्यम से है। आपका कोड ठीक संकलन होगा यदि आप की तर्ज पर कुछ करने के लिए इस प्रकार थे:

template <class T> 
T round (T r) { 
    return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); 
} 

आपका लिंकर शिकायत करना बंद कर देगा और आप अपनी आवश्यकताओं के सभी के लिए एक भी समारोह होगा।

इस समाधान को प्रकार के लक्षणों के साथ बेहतर किया जा सकता है। boost::is_floating_point और boost::enable_if

+0

आप धोखा देते हैं, लेकिन एक अच्छे तरीके से। यह काम करता हैं। यह कुछ परिदृश्यों के लिए भी सबसे अच्छा समाधान है! धन्यवाद। – javaLover

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