2010-05-05 1 views
9

में स्टेटिक कॉन्स डबल डबल स्टैटिक कॉन्स वैरिएबल का उपयोग करने का यह सही तरीका है? अपने शीर्ष स्तर वर्ग (आकार)सी ++

#ifndef SHAPE_H 
#define SHAPE_H 

class Shape 
{ 
public: 

    static const double pi; 
private: 
    double originX; 
    double originY; 
}; 

const double Shape::pi = 3.14159265; 

#endif 

और फिर बाद में एक वर्ग है कि आकार का विस्तार में में, मैं आकार :: अनुकरणीय का उपयोग करें। मुझे एक लिंकर त्रुटि मिलती है। मैंने कॉन्स डबल आकार :: पीआई = 3.14 ... को Shape.cpp फ़ाइल में ले जाया और मेरा प्रोग्राम फिर संकलित करता है। ऐसा क्यों होता है? धन्यवाद।

उत्तर

10

क्योंकि const double Shape::pi = 3.14159265; की Shape::pi और सी परिभाषा है ++ केवल एक प्रतीक (one-definition-rule कहा जाता है यह परिवर्णी शब्द रूप ओडीआर है में आप देख सकते हैं) के के एक एकल परिभाषा अनुमति देता है। जब परिभाषा हेडर फ़ाइल में होती है, तो प्रत्येक अनुवाद इकाई को इसकी परिभाषा मिल जाती है जो उस नियम को तोड़ देती है।

इसे स्रोत फ़ाइल में ले जाकर, आपको केवल एक ही परिभाषा मिलती है।

+0

मेरे पास एक ही समस्या है। समस्या यह है कि, यदि यह एक लाइब्रेरी है, और मैं चाहता हूं कि मेरे उपयोगकर्ता .h फ़ाइल में आकार :: pi के मान को देखना चाहते हैं, लेकिन सीपीपी सामग्री नहीं (i.e, अन्य फ़ंक्शन परिभाषा)। मुझे क्या करना चाहिए? –

3

ऐसा इसलिए होता है क्योंकि आप एक बार आकार :: पीआई को परिभाषित नहीं कर सकते हैं। यह एक बार परिभाषित किया गया है जब आप Shape.hpp में Shape.h शामिल करते हैं, और फिर दूसरी बार जब आप किसी अन्य cpp फ़ाइल में Shape.h का उपयोग करते हैं। जब आप एक साथ प्रोग्राम करने के लिए जाते हैं तो लिंकर कई परिभाषाओं के कारण बार्फ़ होगा।

1

लाइन const double Shape::pi = 3.14159265; आपकी Shape.cpp फ़ाइल में होना चाहिए। हेडर फ़ाइल चर घोषित करने के लिए है। आप केवल एक चर को परिभाषित कर सकते हैं, इसलिए इसे .cpp में किया जाना चाहिए। हेडर फ़ाइल कहती है कि इन चर और कार्यों का उपयोग कैसे करें, सीपीपी फ़ाइल कहती है कि क्या करना है।

12

स्टेटिक फ़्लोटिंग-पॉइंट डेटा सदस्यों को एक स्रोत फ़ाइल में परिभाषित और प्रारंभ किया जाना चाहिए। एक परिभाषा नियम शीर्षलेख में class {} ब्लॉक के बाहर एक परिभाषा को रोकता है, और class {} ब्लॉक के अंदर केवल अभिन्न डेटा सदस्यों को प्रारंभ करने की अनुमति है।

यह भी दुर्भाग्यपूर्ण है क्योंकि, एक बीजगणितीय मूल्य होने के कारण, हाथ पर तत्काल मूल्य होने के कारण, वैश्विक चर से लोड होने के बजाय अनुकूलन के लिए अच्छा हो सकता है। (हालांकि अंतर असंगत होने की संभावना है।)

हालांकि कोई समाधान है!

class Shape 
{ 
public: 
    static double pi() 
     { return 3.14159265; } 

private: 
    double originX; 
    double originY; 
}; 

इनलाइन समारोह परिभाषाएँ, स्थिर भी शामिल होते हैं, class{} ब्लॉक के अंदर की अनुमति है।

इसके अलावा, मैं M_PI<math.h> से उपयोग करने की अनुशंसा करता हूं, जिसे आपको <cmath> से भी प्राप्त करना चाहिए।

+0

इसके अतिरिक्त: टेम्पलेट्स के पास अलग-अलग संबंध हैं, इसलिए आप परिभाषा को – justin

+2

@ जस्टिन बनाने के लिए टेम्पलेट का उपयोग कर सकते हैं: मुझे नहीं लगता कि अतिरिक्त जटिलता को छोड़कर 'टेम्पलेट' आपको यहां कुछ भी प्राप्त करता है। – Potatoswatter

+0

एक टेम्पलेट चीजों को जटिल कर सकता है, लेकिन यह संभावित रूप से आपको "क्लास टेम्पलेट के स्थिर डेटा सदस्य" (अन्य ओडीआर अपवादों के बीच) के लिए एक परिभाषा नियम के लिए अपवाद खरीदता है। सी ++ मानक के 3.2/5 और 14.5.1.3 देखें। –

1

आदिम डेटा प्रकार के लिए (int की तरह, डबल लेकिन [] चार नहीं) आप भी वर्ग परिभाषा के दायरे में लगातार हेडर फाइल के भीतर, उदा परिभाषित कर सकते हैं .:

class Shape 
{ 
public: 
    static const double pi = 3.14159265; 

private: 
    double originX; 
    double originY; 
}; 

यह बेहतर संकलक अनुकूलन की अनुमति देगा।

संपादित करें: जैसा कि डेनिस ने नीचे बताया है, केवल अभिन्न प्रकारों के लिए अनुमति है, न कि डबल या फ्लोट डेटा प्रकारों के लिए (हालांकि कुछ कंपाइलर इसे अनुमति देंगे)।

+1

आप केवल अभिन्न और enum प्रकारों के लिए ऐसा कर सकते हैं। फ़्लोटिंग पॉइंट प्रकारों की अनुमति नहीं है। –

+0

@ डेनिस: ओह! तुम सही हो! मैं संकलक द्वारा बेवकूफ़ बना दिया गया था (जीसीसी और आईसीसी कक्षा के भीतर शुरू होने के लिए स्थिर स्थिर डबल डबल) ... – Oliver

5

आप अपने संकलक को C++0x झंडा डालने का एक तरीका है, तो आप ऐसा करने में सक्षम किया गया है जाएगा:

ifndef SHAPE_H 
#define SHAPE_H 

class Shape 
{ 
public: 

    static constexpr double pi = 3.14159265; 
private: 
    double originX; 
    double originY; 
}; 

#endif 

C++0x में आप अभिन्न की तुलना में अन्य प्रकार की स्थिरांक एक्सप्रेशन का उपयोग करने में सक्षम हैं। यह आपको अपने निरंतर परिवर्तनीय स्थान पर घोषित करने और परिभाषित करने में सक्षम बनाता है।

0

एक फ़ंक्शन लागू करें जो सूची में किसी मान की अनुक्रमणिका को लौटाता है यदि यह मौजूद है। अन्यथा यदि कोई मूल्य नहीं है तो वापसी -1। यदि सूची में एक ही मान एक से अधिक बार मौजूद है तो पहला मान नीचे से हटा दिया गया है।

public static intfindFromLast (List <Double> l, double value) {///…}