हेडर और सीपीपी फ़ाइल में वर्ग कोड को अलग करना


169

मैं एक साधारण श्रेणी के कार्यान्वयन और घोषणाओं के कोड को नए हेडर और सीपीपी फ़ाइल में अलग करने के तरीके पर उलझन में हूं। उदाहरण के लिए, मैं निम्नलिखित वर्ग के लिए कोड को कैसे अलग करूंगा?

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y)
  {
    gx = x;
    gy = y;
  }

  int getSum()
  {
    return gx + gy;
  }
};

12
बस टिप्पणियों के एक जोड़े: निर्माता को हमेशा शरीर में सदस्यों को स्थापित करने के बजाय एक प्रारंभ सूची का उपयोग करना चाहिए। एक अच्छी और सरल व्याख्या के लिए, देखें: codeguru.com/forum/showthread.php?t=464084 यह भी है, कम से कम अधिकांश स्थानों पर, शीर्ष पर सार्वजनिक क्षेत्र के लिए प्रथागत। यह कुछ भी प्रभावित नहीं करेगा, लेकिन चूंकि सार्वजनिक क्षेत्र आपकी कक्षा का प्रलेखन है, इसलिए यह शीर्ष पर है।
मार्ट

2
@martiert public:शीर्ष पर सदस्य होने से बहुत प्रभावित हो सकता है , अगर उपयोगकर्ता ने उन्हें इस सलाह के अनुसार स्थानांतरित किया है - लेकिन सदस्यों के बीच निर्भरता का आदेश दिया था और अभी तक यह पता नहीं था कि सदस्यों को उनकी घोषणा के क्रम में प्रारंभ किया जाता है ;-)
underscore_d

1
@underscore_d जो सच है। लेकिन फिर, हम सभी चेतावनियों को त्रुटियों के रूप में संकलित कर रहे हैं और सभी चेतावनी हम सोच सकते हैं, है ना? यह कम से कम आपको बताएगा कि आप इसे खराब कर रहे हैं, लेकिन हाँ, लोग थोड़ी चेतावनियों का उपयोग करते हैं, और बस उन्हें अनदेखा करते हैं :(
शहीद

@martiert अच्छा बिंदु, थोड़े भूल गए कि चेतावनी उत्पन्न करता है - अगर केवल चेतावनियों को ज्यादातर :-) द्वारा पढ़ा गया था तो मैं उनका उपयोग करता हूं और उन्हें दूर करने की कोशिश करता हूं। कुछ अपरिहार्य हैं - इसलिए मैं कहता हूं 'चेतावनी के लिए धन्यवाद, लेकिन मुझे पता है कि मैं क्या कर रहा हूं!' - लेकिन बाद में भ्रम से बचने के लिए सबसे बेहतर हैं।
अंडरस्कोर_ड

शीर्ष पर सार्वजनिक क्षेत्र होना एक शैली है, यह भी कई लोगों ने दुर्भाग्य से मेरी राय में अपनाया है। इसके अतिरिक्त, आपको कुछ बातों को ध्यान में रखने की आवश्यकता है जैसा कि @martiert ने उल्लेख किया है।
वासिलिस

जवाबों:


232

क्लास की घोषणा हेडर फ़ाइल में जाती है। यह महत्वपूर्ण है कि आप #ifndefशामिल गार्डों को जोड़ते हैं, या यदि आप एक एमएस प्लेटफॉर्म पर हैं तो आप भी उपयोग कर सकते हैं #pragma once। इसके अलावा, मैंने निजी को छोड़ दिया है, डिफ़ॉल्ट रूप से C ++ वर्ग के सदस्य निजी हैं।

// A2DD.h
#ifndef A2DD_H
#define A2DD_H

class A2DD
{
  int gx;
  int gy;

public:
  A2DD(int x,int y);
  int getSum();

};

#endif

और कार्यान्वयन CPP फ़ाइल में जाता है:

// A2DD.cpp
#include "A2DD.h"

A2DD::A2DD(int x,int y)
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

52
याद रखें कि यदि आप टेम्प्लेट प्रोग्रामिंग कर रहे हैं, तो आपको सब कुछ .h फ़ाइल में रखना होगा ताकि कंपाइलर संकलन के क्षण में सही कोड को तुरंत हटा देगा।
लिनलेओ

2
क्या आपके पास #ifndefहेडर में सामान है?
फेरेनक डेक

4
तो इसका मतलब यह है कि आपकी हेडर फ़ाइल में शामिल सभी फाइलें निजी सदस्यों को "देखेंगी"। यदि उदाहरण के लिए आप एक लीब और उसके हेडर को प्रकाशित करना चाहते हैं, तो आपको कक्षा के निजी सदस्यों को दिखाना होगा?
गौथियर

1
नहीं, अद्भुत निजी कार्यान्वयन मुहावरा है: en.wikipedia.org/wiki/Opaque_pointer आप इसका उपयोग कार्यान्वयन विवरण छिपाने के लिए कर सकते हैं।
फेरेनक डेक

3
शब्दांकन के साथ लघु नाइटपिक: "श्रेणी की घोषणा हेडर फ़ाइल में जाती है"। यह वास्तव में एक घोषणा है, लेकिन यह भी एक परिभाषा है, लेकिन जैसा कि बाद में पूर्व शामिल है मैं यह कहूंगा कि वर्ग परिभाषा हेडर फ़ाइल में जाती है। अनुवाद इकाई में, आपके पास सदस्य कार्यों की परिभाषा है, न कि वर्ग की परिभाषा। मैं मानता हूँ, यह एक छोटे से संपादन के लायक हो सकता है?
लुब्रीग करें

17

सामान्य तौर पर आपके .h में कक्षा की सुरक्षा होती है, जो आपके सभी डेटा और आपके सभी विधि घोषणाओं में होती है। आपके मामले में यह पसंद है:

A2DD.h:

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y);    
  int getSum();
};

और फिर आपके .cpp में इस तरह से विधियों का कार्यान्वयन शामिल है:

A2DD.cpp:

A2DD::A2DD(int x,int y)
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

7

इस सवाल पर ठोकर खा रहे पाठकों के लिए यह कहना महत्वपूर्ण है कि जब आप जिस परियोजना को फाइलों में विभाजित करना चाहते हैं उस मामले में स्वीकृत जवाब की प्रक्रिया की आवश्यकता नहीं है। यह केवल तब आवश्यक है जब आपको एकल कक्षाओं के कई कार्यान्वयन की आवश्यकता हो। यदि प्रति वर्ग में आपका कार्यान्वयन एक है, तो प्रत्येक के लिए सिर्फ एक हेडर फ़ाइल पर्याप्त है।

इसलिए, स्वीकृत उत्तर के उदाहरण से केवल इस भाग की आवश्यकता है:

#ifndef MYHEADER_H
#define MYHEADER_H

//Class goes here, full declaration AND implementation

#endif

#Ifndef आदि प्रीप्रोसेसर परिभाषाएँ इसे कई बार उपयोग करने की अनुमति देती हैं।

पुनश्च। C / C ++ का 'गूंगा' होने का एहसास होने पर विषय स्पष्ट हो जाता है और #include केवल "इस स्थान पर इस पाठ को डंप" कहने का एक तरीका है।


क्या आप कोड संगठन की इस पद्धति के लिए "स्प्लिट" फ़ाइलों को डालकर .cppया .hवास्तव में केवल "अच्छा" कर सकते हैं?
बेनी जोबिगन

1
मैंने सोचा था कि कुछ परियोजनाएं हेडर और (सिंगल) कार्यान्वयन फ़ाइलों को विभाजित करती हैं ताकि वे हेडर फ़ाइलों को कार्यान्वयन के स्रोत कोड को प्रकट किए बिना आसानी से वितरित कर सकें।
कार्ल जी

मुझे खुशी है कि आपने इसे इंगित किया क्योंकि मैंने मूल रूप से C ++ पर सीखा था, फिर कई साल पहले C # में स्विच किया और हाल ही में फिर से बहुत सी C ++ कर रहा हूं और मैं भूल गया कि फ़ाइलों को विभाजित करने वाले थकाऊ और कष्टप्रद कैसे है और अभी सब कुछ डाल दिया है हेडर। मैं किसी को भी अच्छे कारणों की तलाश में चारों ओर खोज रहा था ऐसा करने के लिए नहीं जब मैंने यह पाया। @CarlG के पास एक अच्छा बिंदु है, लेकिन उस परिदृश्य के अलावा मुझे लगता है कि यह सब इनलाइन करने का तरीका है।
पीटर मूर

6

मूल रूप से फ़ंक्शन घोषणा / परिभाषाओं का एक संशोधित सिंटैक्स:

a2dd.h

class A2DD
{
private:
  int gx;
  int gy;

public:
  A2DD(int x,int y);

  int getSum();
};

a2dd.cpp

A2DD::A2DD(int x,int y)
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

5

A2DD.h

class A2DD
{
  private:
  int gx;
  int gy;

  public:
  A2DD(int x,int y);

  int getSum();
};

A2DD.cpp

  A2DD::A2DD(int x,int y)
  {
    gx = x;
    gy = y;
  }

  int A2DD::getSum()
  {
    return gx + gy;
  }

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

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


4

आप शीर्षक फ़ाइल में घोषणाएँ छोड़ देते हैं:

class A2DD
{
  private:
  int gx;
  int gy;

  public:
    A2DD(int x,int y); // leave the declarations here
    int getSum();
};

और परिभाषाओं को कार्यान्वयन फ़ाइल में रखें।

A2DD::A2DD(int x,int y) // prefix the definitions with the class name
{
  gx = x;
  gy = y;
}

int A2DD::getSum()
{
  return gx + gy;
}

आप दोनों को मिला सकते हैं (छोड़ दें getSum() उदाहरण के लिए हेडर में परिभाषा )। यह उपयोगी है क्योंकि यह संकलक को उदाहरण के लिए इनलाइनिंग में बेहतर मौका देता है। लेकिन इसका मतलब यह भी है कि कार्यान्वयन को बदलना (यदि हेडर में छोड़ दिया गया है) सभी अन्य फ़ाइलों के पुनर्निर्माण को ट्रिगर कर सकता है जिसमें हेडर शामिल हैं।

ध्यान दें कि टेम्प्लेट के लिए, आपको इसे हेडर में रखना होगा।


1
हेडर फ़ाइल में निजी सदस्यों और फ़ंक्शंस को डालना, कार्यान्वयन विवरणों को लीक करना नहीं माना जाता है?
जेसन

1
@ जेसन, की तरह। वे आवश्यक कार्यान्वयन विवरण हैं। उदाहरण के लिए, मुझे यह जानना होगा कि स्टैक पर एक वर्ग कितना स्थान लेगा। अन्य संकलन इकाइयों के लिए फ़ंक्शन कार्यान्वयन आवश्यक नहीं है।
पॉल ड्रेपर

1

आमतौर पर आप हेडर फ़ाइल में केवल घोषणाएँ और वास्तव में छोटी इनलाइन फ़ंक्शंस डालते हैं:

उदाहरण के लिए:

class A {
 public:
  A(); // only declaration in the .h unless only a short initialization list is used.

  inline int GetA() const {
    return a_;
  }

  void DoSomethingCoplex(); // only declaration
  private:
   int a_;
 };

0

मैं भी अपने उदाहरण का उल्लेख नहीं होगा, क्योंकि यह एक सामान्य जवाब के लिए काफी सरल (उदाहरण के लिए यह टेम्प्लेट काम करता है, जो आप के हैडर पर उन्हें लागू करने के लिए मजबूर नहीं होते हैं) है, क्या मैं एक सामान्य नियम के रूप में पालन करें pimpl मुहावरा

आपके पास तेजी से संकलन समय और सिंटैक्टिक चीनी प्राप्त करने के कुछ काफी फायदे हैं:

class->member के बजाय class.member

एकमात्र दोष आपके द्वारा भुगतान किए गए अतिरिक्त सूचक हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.