2013-02-22 28 views
7

my_test.hक्या एक कॉन्स स्थिर चर को C++ हेडर फ़ाइल में प्रारंभ किया जाना चाहिए?

#ifndef MY_TEST 
#define MY_TEST 

struct obj { 
    int x; 
    int y; 
}; 

class A { 
private: 
    const static int a=100; 
    const static obj b; 
}; 

const obj A::b={1,2}; 

#endif 

जब सीपीपी संकलन इस हेडर फाइल का उपयोग कर, एक त्रुटि 'multiple definition of 'A::b' होता है।

  1. यह तब क्यों है जब मैं गार्ड मैक्रो का उपयोग कर रहा हूं?
  2. A::a क्यों एरो उत्पन्न नहीं करता है? (मैं कोड const static obj b={1,2}class A में नहीं लिख सकते हैं)

उत्तर

4

यह तब क्यों है जब मैं गार्ड मैक्रो का उपयोग कर रहा हूं?

हैडर गार्ड केवल एक बार में एक ही translation unit में कई अनुवाद इकाइयों में नहीं की तुलना में अधिक हेडर फाइल सामग्री के शामिल किए जाने को रोकने के।

क्यों A::a है त्रुटि संदेश नहीं है (मैं class A में कोड const static obj b={1,2} नहीं लिख सकते हैं)

In-class initialization स्थिर डेटा सदस्यों के लिए एक विशेष मामले के रूप संकलक द्वारा अनुमति दी है शाब्दिक प्रकार का आधार। आपका उदाहरण एक श्रेणी के प्रारंभिक है।

const A::b जहां हेडर शामिल हो जाता है प्रत्येक अनुवाद इकाई में एक ही प्रतीक नाम को परिभाषित करता है और इसलिए one definition rule टूट जाता है।

आपको परिभाषा को एक और केवल एक स्रोत सीपीपी फ़ाइल में स्थानांतरित करने की आवश्यकता है ताकि इसे केवल एक बार परिभाषित किया जा सके।

+2

ओपी के लिए, शुरुआत के रूप में, "आपको आवश्यकता है" सही है। हालांकि, एक पूर्ण तकनीकी कथन के रूप में यह नहीं है, क्योंकि वर्ग टेम्पलेट्स के लिए एक ओडीआर छूट है। जिसका अर्थ यह है कि तकनीकी रूप से, यदि इसके लिए वास्तविक आवश्यकता है, तो कोई एक वर्ग टेम्पलेट में स्थिर स्थिरता को परिभाषित कर सकता है और फिर मनमाने ढंग से विशेषज्ञता प्राप्त कर सकता है। इसे कभी-कभी टेम्पलेटेड निरंतर चाल के रूप में जाना जाता है। एक कार्यान्वयन फ़ाइल से बचने के लिए एक और व्यावहारिक तरीका, यदि कोई करता है, तो इनलाइन फ़ंक्शन के माध्यम से निरंतर पहुंच प्रदान करना है (जो स्थानीय के रूप में स्थिर हो सकता है)। ' –

+0

@ एएलएफ: मैं आपकी टिप्पणी के अनुसार सहमत हूं। वास्तव में यह जानकारी का एक अच्छा टुकड़ा है। –

0

समस्या A::b की अपनी परिभाषा एक प्रकार नहीं होता है। एक वैध परिभाषा होने के लिए, यह होना चाहिए:

const obj A::b = {1, 2}; 

यह संकलन त्रुटि से छुटकारा मिल जाएगा, लेकिन अगर आप एक से अधिक स्रोत फ़ाइल में इस शीर्ष लेख शामिल आप अभी भी लिंकर त्रुटियों मिलेगा, क्योंकि A::b हो जाएगा तब गुणा करें। आपको परिभाषा को .cpp फ़ाइल में ले जाना चाहिए।

0

भले ही आपके पास हेडर गार्ड है या नहीं, इस बात को ध्यान में रखते हुए कि हेडर फ़ाइल में प्रारंभिकता का अर्थ यह होगा कि आपको प्रत्येक स्रोत फ़ाइल में A::b का उदाहरण मिलेगा जिसमें हेडर फ़ाइल शामिल है। इसलिए लिंकर त्रुटि।

तो, आम तौर पर बोलना, यह संभव है, लेकिन एक अच्छा विचार नहीं है।

1

आलोक पहले से ही अपने प्रश्न का उत्तर है, लेकिन यहाँ अंगूठे का कुछ सरल नियमों कर रहे हैं, आसानी से याद के रूप में:

  1. घोषणाएं ज फ़ाइल
  2. परिभाषाएँ में जाना में जाओसीपीपी फ़ाइल

इसलिए, स्थिर सदस्यों घोषित .h फ़ाइल में, और फिर .cpp फ़ाइल में परिभाषित करने की आवश्यकता है। अपने मामले में, घोषणाओं के लिए वाक्यविन्यास को ठीक करें और फिर उन्हें "my_test.cpp" फ़ाइल पर ले जाएं।

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