সি ++ এ ফরওয়ার্ড ডিক্লেয়ারেশন কি?


215

এ: http://www.learncpp.com/cpp-tutorial/19-header-files/

নিম্নলিখিতটি উল্লেখ করা হয়েছে:

add.cpp:

int add(int x, int y)
{
    return x + y;
}

main.cpp:

#include <iostream>

int add(int x, int y); // forward declaration using function prototype

int main()
{
    using namespace std;
    cout << "The sum of 3 and 4 is " << add(3, 4) << endl;
    return 0;
}

আমরা একটি অগ্রণী ঘোষণা ব্যবহার করেছি যাতে সংকলকটি জানতে পারে "add যখন সংকলন করার সময় " ছিল main.cpp। পূর্বে উল্লিখিত হিসাবে, আপনি যে ফাংশনটি অন্য ফাইলে ব্যবহার করতে চান তা ব্যবহার করতে চান এমন প্রতিটি ফাংশনের জন্য ফরওয়ার্ড ডিক্লেয়ারেশন লিখে দ্রুত ক্লান্তি পেতে পারে।

আপনি আরও " ফরোয়ার্ড ঘোষণা " ব্যাখ্যা করতে পারেন ? যদি আমরা এটি main()ফাংশনে ব্যবহার করি তবে সমস্যা কী ?


1
একটি "ফরওয়ার্ড ডিক্লেয়ারেশন" আসলেই কেবল একটি ঘোষণা। এই উত্তরটি দেখুন (শেষ): স্ট্যাকওভারফ্লো
এসবিআই

উত্তর:


381

সি ++ এ কেন ফরওয়ার্ড-ডিক্লেয়ার প্রয়োজনীয়

সংকলকটি নিশ্চিত করতে চায় যে আপনি কোনও বানান ভুল করেছেন না বা ফাংশনে ভুল সংখ্যক তর্ক যুক্ত করেছেন passed সুতরাং, এটি জোর দিয়েছিল যে এটি ব্যবহারের আগে এটি 'অ্যাড' (বা অন্য কোনও ধরণের, শ্রেণি বা ফাংশন) এর ঘোষণাকে প্রথম দেখে।

এটি সত্যিই কেবল সংকলকটি কোডটি যাচাই করার জন্য আরও ভাল কাজ করার অনুমতি দেয় এবং এটিকে আলগা প্রান্তটি পরিষ্কার করার অনুমতি দেয় যাতে এটি একটি ঝরঝরে চেহারা অবজেক্ট ফাইল তৈরি করতে পারে। যদি আপনাকে জিনিসগুলি ঘোষণা করতে এগিয়ে না যেতে হয়, সংকলকটি একটি অবজেক্ট ফাইল তৈরি করবে যাতে ফাংশনটি 'অ্যাড' কী হতে পারে তা সম্পর্কে সমস্ত সম্ভাব্য অনুমান সম্পর্কে তথ্য থাকতে হবে। এবং লিঙ্কারে খুব চালাক যুক্তি থাকতে হবে যা চেষ্টা করার জন্য এবং আসলে 'কল' যুক্ত করতে চাইলে আপনি কোন 'যুক্ত' করতে পারেন, যখন 'যোগ' ফাংশনটি কোনও ভিন্ন অবজেক্ট ফাইলে বাস করতে পারে যখন লিঙ্কার তার সাথে যুক্ত হয় যা উত্পাদন করতে যোগ করে একটি dll বা উদাহরণ। লিঙ্কারটি ভুল অ্যাড পেতে পারে এটি সম্ভব possible বলুন আপনি ইন্ট অ্যাড (ইন্ট এ, ফ্লোট বি) ব্যবহার করতে চেয়েছিলেন, তবে দুর্ঘটনাক্রমে এটি লিখতে ভুলে গিয়েছিলেন, তবে লিঙ্কারটি ইতিমধ্যে একটি বিদ্যমান ইনট অ্যাড খুঁজে পেয়েছে (int a, int খ) এবং ভাবা হয়েছে যে এটি সঠিক এবং পরিবর্তে এটি ব্যবহার করেছে। আপনার কোডটি সংকলন করবে, তবে আপনি যা প্রত্যাশা করেছিলেন তা করছে না।

সুতরাং, কেবল বিষয়গুলি স্পষ্ট রাখতে এবং অনুমান করা ইত্যাদি এড়ানোর জন্য, সংকলক জোর দিয়েছিল যে আপনি এটি ব্যবহারের আগে সমস্ত কিছু ঘোষণা করুন।

ঘোষণা এবং সংজ্ঞা মধ্যে পার্থক্য

একদিকে যেমন, একটি ঘোষণা এবং সংজ্ঞা মধ্যে পার্থক্য জানা গুরুত্বপূর্ণ। একটি ঘোষণাপত্রটি কেবল কিছু দেখতে কেমন তা প্রদর্শন করার জন্য যথেষ্ট কোড দেয়, সুতরাং কোনও ফাংশনের জন্য, এটি রিটার্নের ধরণ, কনভেনশন, পদ্ধতির নাম, আর্গুমেন্ট এবং তাদের ধরণগুলি কল করে। তবে পদ্ধতির কোডটি প্রয়োজন নেই। একটি সংজ্ঞা জন্য, আপনি ঘোষণার প্রয়োজন এবং তারপর ফাংশন জন্য কোড।

ফরোয়ার্ড-ডিক্লেয়ারেশন কীভাবে বিল্ডের সময়কে হ্রাস করতে পারে

ইতিমধ্যে ফাংশনটির ঘোষণা রয়েছে এমন শিরোনামকে # অন্তর্ভুক্ত করে আপনি আপনার বর্তমান .cpp বা .h ফাইলে কোনও ফাংশনটির ঘোষণা পেতে পারেন। তবে এটি আপনার সংকলনটিকে ধীর করতে পারে, বিশেষত যদি আপনি আপনার প্রোগ্রামের .cpp পরিবর্তে একটি শিরোনামকে একটি। H এর সাথে অন্তর্ভুক্ত করেন, যেমন # আপনি যে লেখেন তাতে অন্তর্ভুক্ত থাকবে সমস্ত # হেডার অন্তর্ভুক্ত থাকবে আপনি # জন্য অন্তর্ভুক্ত লিখেছেন। হঠাৎ করেই, সংকলকটিতে # অন্তর্ভুক্ত পৃষ্ঠাগুলি এবং কোডের পৃষ্ঠা রয়েছে যা আপনি কেবল এক বা দুটি ফাংশন ব্যবহার করতে চাইলেও এটি সংকলন করতে হবে। এটি এড়াতে, আপনি একটি ফরোয়ার্ড-ডিক্লেয়ারেশন ব্যবহার করতে পারেন এবং কেবলমাত্র ফাইলের শীর্ষে ফাংশনটির ঘোষণাপত্রটি টাইপ করতে পারেন। আপনি যদি কেবল কয়েকটি ফাংশন ব্যবহার করছেন তবে এটি সর্বদা # শিরোনামের সাথে তুলনা করে আপনার সংকলনগুলি আরও দ্রুততর করে তুলতে পারে। সত্যিই বড় প্রকল্পগুলির জন্য,

চক্রীয় রেফারেন্সগুলি ভাঙ্গুন যেখানে দুটি সংজ্ঞা উভয়ই একে অপরকে ব্যবহার করে

অতিরিক্তভাবে, ফরোয়ার্ড-ঘোষণা আপনাকে চক্র ভাঙ্গতে সহায়তা করতে পারে। এখানে দুটি ফাংশন একে অপরকে ব্যবহার করার চেষ্টা করে। যখন এটি ঘটে (এবং এটি করা একেবারে বৈধ জিনিস), আপনি একটি হেডার ফাইল অন্তর্ভুক্ত করতে পারেন, তবে সেই শিরোলেখ ফাইলটি আপনি বর্তমানে যে শিরোনাম ফাইলটি লিখছেন তাতে # অন্তর্ভুক্ত করার চেষ্টা করে .... যা অন্য শিরোনামকে অন্তর্ভুক্ত করে # , যা আপনি লিখছেন এর সাথে # অন্তর্ভুক্ত। আপনি প্রতিটি মস্তকের ফাইলটিকে অন্যটিকে অন্তর্ভুক্ত করার চেষ্টা করে একটি মুরগি এবং ডিমের পরিস্থিতিতে আটকে আছেন। এটি সমাধানের জন্য, আপনি যে কোনও একটি ফাইলের জন্য প্রয়োজনীয় অংশগুলি ফরওয়ার্ড-ডিক্লেয়ার করতে পারেন এবং # ফাইলটি এই ফাইলের বাইরে রেখে যেতে পারেন।

উদাহরণ:

ফাইল কার

#include "Wheel.h"  // Include Wheel's definition so it can be used in Car.
#include <vector>

class Car
{
    std::vector<Wheel> wheels;
};

ফাইল হুইল

হুম ... এখানে গাড়ির ঘোষনা আবশ্যক কারণ হুইলটির একটি গাড়ীর দিকে একটি পয়েন্টার রয়েছে, তবে কার হিটকে এখানে অন্তর্ভুক্ত করা যাবে না কারণ এটি সংকলক ত্রুটির ফলে ঘটবে। যদি কার.হ.কে অন্তর্ভুক্ত করা হত, তবে তারপরে হুইল এইচকে অন্তর্ভুক্ত করার জন্য হুইলহকে অন্তর্ভুক্ত করার জন্য কার হ'ল অন্তর্ভুক্ত করার চেষ্টা করা হবে এবং এটি চিরকালের জন্য চলবে, পরিবর্তে সংকলকটি একটি ত্রুটি উত্থাপন করে। সমাধানটি তার পরিবর্তে গাড়ি ঘোষণা করার জন্য হ'ল:

class Car;     // forward declaration

class Wheel
{
    Car* car;
};

যদি ক্লাস হুইলের এমন পদ্ধতি ছিল যা গাড়ীর কলগুলি কল করতে পারে তবে সেই পদ্ধতিগুলি Wheel.cpp এ সংজ্ঞায়িত করা যেতে পারে এবং Wheel.cpp এখন কোনও চক্রের কারণ ছাড়াই Car.h কে অন্তর্ভুক্ত করতে সক্ষম।


4
ফাংশন দুটি বা অনেক শ্রেণীর জন্য বন্ধুত্বপূর্ণ হয় যখন অগ্রণী ঘোষণাও প্রয়োজনীয়
বরুন

1
আরে স্কট, আপনার গড়নের সময়গুলির বিষয়ে: আপনি কি বলতে পারবেন যে সর্বদা .cpp ফাইলে শিরোনামকে ঘোষণা এবং শিরোনামকে ফরোয়ার্ড করা ভাল? আপনার উত্তর পড়া থেকে এটি প্রদর্শিত হবে প্রদর্শিত হবে, কিন্তু আমি ভাবছি কিছু আছে কিনা?
জেপি

5
@ জিপি এটি একটি ভারসাম্য দ্রুত নির্মাণের জন্য, আমি বলব এটি ভাল অনুশীলন এবং আমি এটি চেষ্টা করার পরামর্শ দিই। তবে, এটি কিছু প্রচেষ্টা এবং কোডের অতিরিক্ত রেখাগুলি গ্রহণ করতে পারে যেগুলি টাইপ নামগুলি যদি এখনও পরিবর্তন করা হয় তবে এটি রক্ষণাবেক্ষণ এবং আপডেট করার প্রয়োজন হতে পারে (যদিও সরঞ্জামগুলি স্বয়ংক্রিয়ভাবে নামকরণের ক্ষেত্রে আরও ভাল হচ্ছে)। সুতরাং একটি বাণিজ্য আছে। আমি এমন কোড বেসগুলি দেখেছি যেখানে কেউ বিরক্ত হয় না। আপনি যদি একই ফরোয়ার্ড সংজ্ঞায়িত করে নিজেকে পুনরাবৃত্তি করে দেখতে পান তবে আপনি এগুলি সর্বদা পৃথক শিরোনামের ফাইলে রেখে দিতে পারেন এবং এর মধ্যে এমন কিছু অন্তর্ভুক্ত করতে পারেন: স্ট্যাকওভারফ্লো
স্কট ল্যাংহ্যাম

ফরওয়ার্ড ডিক্লেয়ারেশনগুলি যখন হেডার ফাইলগুলি একে অপরকে নির্দেশ করে: তখন স্ট্যাকওভারফ্লো.com
নিকোলাস হ্যামিল্টন

1
আমি দেখতে পাচ্ছি এটি আমার দলের অন্যান্য ডেভসরা কোডবেসের সত্যই খারাপ নাগরিক হতে দেয়। আপনার যদি ফরওয়ার্ড ডিক্লেয়ারের সাথে কোনও মন্তব্যের প্রয়োজন না হয়, // From Car.hতবে তারপরে আপনি কিছুটা লোমশ পরিস্থিতি তৈরি করতে পারেন যা গ্যারান্টিযুক্ত রাস্তার নিচে একটি সংজ্ঞা খোঁজার চেষ্টা করছে।
ডাগ্রুমগুলি

25

সংকলকটি বর্তমান অনুবাদ ইউনিটে ব্যবহৃত প্রতিটি প্রতীকটি বর্তমান ইউনিটে পূর্বে ঘোষিত বা না হিসাবে ঘোষিত হয়েছে looks উত্স ফাইলের শুরুতে সমস্ত পদ্ধতি স্বাক্ষর সরবরাহ করার ক্ষেত্রে এটি শৈলীর বিষয় যখন সংজ্ঞাগুলি পরে দেওয়া হয়। এর উল্লেখযোগ্য ব্যবহার হ'ল আপনি যখন অন্য শ্রেণীর সদস্য ভেরিয়েবল হিসাবে কোনও শ্রেণীর পয়েন্টার ব্যবহার করেন।

//foo.h
class bar;    // This is useful
class foo
{
    bar* obj; // Pointer or even a reference.
};

// foo.cpp
#include "bar.h"
#include "foo.h"

সুতরাং, ক্লাসে যখন সম্ভব হবে তখন এগিয়ে-ঘোষণাগুলি ব্যবহার করুন rations যদি আপনার প্রোগ্রামটির কেবল ফাংশন থাকে (হো হেডার ফাইলগুলি সহ), তবে শুরুতে প্রোটোটাইপ সরবরাহ করা কেবল স্টাইলের বিষয়। এটি যেভাবেই হ'ল যদি শিরোলেখ ফাইলটি একটি সাধারণ প্রোগ্রামে উপস্থিত থাকে যা কেবলমাত্র কার্যকরী থাকে।


12

যেহেতু সি ++ উপরে থেকে নীচে পার্স করা হয়েছে, সংকলকটি তাদের ব্যবহার করার আগে বিষয়গুলি সম্পর্কে জানতে হবে। সুতরাং, আপনি রেফারেন্স যখন:

int add( int x, int y )

মূল ফাংশনে সংকলকটির এটি বিদ্যমান রয়েছে তা জানতে হবে। এটি প্রমাণ করার জন্য এটিকে মূল ফাংশনের নীচে নিয়ে যাওয়ার চেষ্টা করুন এবং আপনি একটি সংকলক ত্রুটি পাবেন।

সুতরাং একটি ' ফরোয়ার্ড ঘোষণা ' ঠিক যা বলে তা তাই। এটি এর ব্যবহারের আগে কিছু ঘোষণা করছে।

সাধারণত আপনি একটি শিরোনাম ফাইলটিতে ফরওয়ার্ড ডিক্লেয়ারেশন অন্তর্ভুক্ত করবেন এবং তারপরে সেই হেডার ফাইলটি একইভাবে অন্তর্ভুক্ত করবেন যেভাবে আইস্ট্রিম অন্তর্ভুক্ত রয়েছে।


12

সি ++ এ " ফরোয়ার্ড ডিক্লেয়ারেশন " শব্দটি বেশিরভাগ ক্ষেত্রে কেবল শ্রেণির ঘোষণার জন্য ব্যবহৃত হয় । কোনও শ্রেণীর "ফরওয়ার্ড ডিক্লেয়ারেশন" সত্যিকার অর্থে একটি সাধারণ শ্রেণির ঘোষণা কেন, এই উত্তরটি দেখুন (শেষ)) একটি অভিনব নাম সহ একটি ।

অন্য কথায়, "ফরোয়ার্ড" পদটিতে কেবলমাত্র ব্যালট যুক্ত করে, যেহেতু এটি কোনও কিছু সনাক্তকারী হিসাবে আগে ঘোষণাপত্র হিসাবে ঘোষণা হিসাবে এতদূর এগিয়ে যেতে দেখা যায় ব্যবহারের এটি ।

( কোনও সংজ্ঞার বিপরীতে ঘোষণা কী কী , আবার দেখুন সংজ্ঞা এবং ঘোষণার মধ্যে পার্থক্য কী? )


2

সংকলকটি যখন দেখবে তখন এর add(3, 4)অর্থ কী তা জানা দরকার। ফরোয়ার্ড ঘোষণার সাথে আপনি মূলত সংকলককে বলুন যে addএটি একটি ফাংশন যা দুটি ints লাগে এবং একটি পূর্বাবস্থায় ফিরে আসে। সংকলকটির জন্য এটি গুরুত্বপূর্ণ তথ্য কারণ এটি স্ট্যাকের মধ্যে সঠিক উপস্থাপনে 4 এবং 5 লাগাতে হবে এবং অ্যাড দ্বারা ফিরে আসা জিনিসটি কী ধরণের তা জানতে হবে।

এ সময় কম্পাইলার সম্পর্কে চিন্তিত নয় প্রকৃত বাস্তবায়ন add, অর্থাত্ যেখানে এটি (বা যদি হয় এমনকি একটি) এবং এটি যদি প্রনয়ন। যা পরে দৃশ্যে আসে, পরে যখন linker প্রার্থনা করা হয় সোর্স ফাইলের কম্পাইলেশনের।


1
int add(int x, int y); // forward declaration using function prototype

আপনি আরও "ফরোয়ার্ড ঘোষণা" ব্যাখ্যা করতে পারেন? যদি আমরা এটিকে মূল () ফাংশনে ব্যবহার করি তবে সমস্যা কী?

এটা যেমন হয় #include"add.h"। আপনি যদি জানেন, প্রিপ্রোসেসর আপনি যে ফাইলটি উল্লেখ করেছেন সেটিকে প্রসারিত #includeকরে .cpp ফাইলে যেখানে আপনি #includeনির্দেশিকা লেখেন । তার মানে, আপনি যদি লিখেন তবে আপনি #include"add.h"একই জিনিসটি পান, এটি যেন আপনি "ফরোয়ার্ড ডিক্লেয়ারেশন" করছেন।

আমি ধরে নিচ্ছি যে add.hএই লাইন আছে:

int add(int x, int y); 

1

একটি দ্রুত সংযোজন সম্পর্কিত: সাধারণত আপনি সেই ফরোয়ার্ড রেফারেন্সগুলি ফাংশন / ভেরিয়েবল ইত্যাদি প্রয়োগ করা হয় এমন .c (পিপি) ফাইলের অন্তর্ভুক্ত একটি শিরোনাম ফাইলে রাখেন। আপনার উদাহরণে এটি দেখতে এইরকম হবে: add.h:

extern int add (int a, int b);

বহিরাগত কীওয়ার্ডটি বলে যে ফাংশনটি আসলে একটি বাহ্যিক ফাইলে ঘোষণা করা হয় (এটি একটি লাইব্রেরিও হতে পারে ইত্যাদি)। আপনার main.c এর মত দেখতে হবে:

# অন্তর্ভুক্ত 
# "add.h" অন্তর্ভুক্ত করুন

প্রধান প্রধান ()
{
।
।
।


তবে, আমরা কি কেবল ঘোষণাকে হেডার ফাইলটিতে রাখি না? আমি মনে করি এই কারণেই ফাংশনটি "add.cpp" এ সংজ্ঞায়িত করা হয়েছে, এবং এভাবে ফরোয়ার্ড ডিক্লেয়ারেশন ব্যবহার করে? ধন্যবাদ।
সরলতা

0

একটি সমস্যা হ'ল এটি যে সংকলকটি জানে না, আপনার ফাংশন দ্বারা কোন ধরণের মান সরবরাহ করা হয়; ধরে নেওয়া হয়, ফাংশনটি intএই ক্ষেত্রে একটি ফেরত দেয় তবে এটি ভুল হতে পারে হিসাবে এটি সঠিক হতে পারে। অন্য সমস্যাটি হ'ল, যেটি সংকলকটি জানে না, আপনার ফাংশনটি কোন ধরণের যুক্তি প্রত্যাশা করে, এবং আপনাকে সতর্ক করতে পারে না, যদি আপনি ভুল ধরণের মানগুলি পাস করেন। বিশেষ "পদোন্নতি" বিধি রয়েছে, যা পাস করার সময় প্রযোজ্য হয়, একটি অঘোষিত ফাংশনে ভাসমান পয়েন্টের মানগুলি বলে (সংকলকটি ডাবল টাইপ করতে তাদের প্রসারিত করতে হবে), যা প্রায়শই হয় না, যা ফাংশনটি আসলে প্রত্যাশা করে, বাগগুলি খুঁজে পাওয়া শক্ত করে তোলে রান-টাইমে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.