আপনি যখন সি না করতে পারেন তখন কেন সি ++ এ শিরোনাম ফাইলের অভ্যন্তরে পদ্ধতির সংজ্ঞা থাকতে পারে?


23

সি তে, আপনার শিরোনাম ফাইলের ভিতরে ফাংশন সংজ্ঞা / বাস্তবায়ন থাকতে পারে না। তবে, সি ++ এ আপনি শিরোনাম ফাইলের অভ্যন্তরে সম্পূর্ণ পদ্ধতি প্রয়োগ করতে পারেন। আচরণ আলাদা কেন?

উত্তর:


28

সি-তে, আপনি যদি একটি শিরোনাম ফাইলে একটি ফাংশন সংজ্ঞায়িত করেন, তবে সেই ফাংশনটি প্রতিটি মডিউলে উপস্থিত হবে যা সংকলিত রয়েছে যা সেই শিরোলেখ ফাইলটি অন্তর্ভুক্ত করে, এবং ফাংশনের জন্য একটি সর্বজনীন প্রতীক রফতানি করা হবে। সুতরাং যদি ফাংশন অ্যাডিটআপটি শিরোনামে সংজ্ঞায়িত করা হয়, এবং foo.c এবং বার.c উভয়ই শিরোলেখ অন্তর্ভুক্ত করে, তবে foo.o এবং বার.ও উভয়ই অ্যাডিটআপের অনুলিপিগুলিকে অন্তর্ভুক্ত করবে।

আপনি যখন এই দুটি অবজেক্ট ফাইল একসাথে লিঙ্ক করতে যান, লিঙ্কারটি দেখতে পাবে যে প্রতীক অ্যাডিটআপটি একাধিকবার সংজ্ঞায়িত হয়েছে, এবং এটির অনুমতি দেবে না।

আপনি যদি ফাংশনটি স্থিতিশীল হিসাবে ঘোষণা করেন তবে কোনও প্রতীক রফতানি হবে না। Foo.o এবং bar.o অবজেক্ট ফাইলগুলি এখনও ফাংশনের জন্য কোডের পৃথক অনুলিপিগুলিকে ধারণ করবে এবং তারা সেগুলি ব্যবহার করতে সক্ষম হবে, তবে লিঙ্কারটি ফাংশনের কোনও অনুলিপি দেখতে সক্ষম হবে না, তাই এটি অভিযোগ করবেন না অবশ্যই, অন্য কোনও মডিউল ফাংশনটি দেখতে পাবে না। এবং আপনার প্রোগ্রামটি একই ফাংশনের দুটি অভিন্ন অনুলিপি সহ ফুলে উঠবে।

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

সুতরাং, আপনি সি এর শিরোনাম ফাইলটিতে ফাংশন সংজ্ঞা থাকতে পারে, এটি কেবল খারাপ শৈলী, খারাপ ফর্ম, এবং একটি চারপাশের খারাপ ধারণা।

("ডিক্লেয়ার" করার অর্থ, আমি কোনও দেহ ছাড়াই একটি ফাংশন প্রোটোটাইপ সরবরাহ করব; "সংজ্ঞায়িত" দ্বারা আমি ফাংশন বডিটির আসল কোড সরবরাহ করব; এটি স্ট্যান্ডার্ড সি পরিভাষা)


2
এটি কোনও খারাপ ধারণা নয় - এই ধরণের জিনিসগুলি এমনকি জিএনইউ লিবিসি শিরোনামেও পাওয়া যায়।
এসকে-যুক্তি

তবে শর্তসাপেক্ষ সংকলনের নির্দেশে হেডার ফাইলটি মোড়ক সম্পর্কিত কী? তারপরে, শিরোনামে ঘোষিত ও সংজ্ঞায়িত ফাংশন সহ, এটি কেবল একবার লোড হবে। আমি সি তে নতুন, তাই আমার ভুল বোঝাবুঝি হতে পারে।
ব্যবহারকারীর 305964

2
@ পেপিরো সমস্যা হ'ল কম্পাইলারের একক রান চলাকালীন মোড়ানো কেবল সুরক্ষা দেয়। সুতরাং যদি foo.c এক রানে foo.o সংকলিত হয়, বার কোড থেকে অন্যটিতে বার.ও, এবং foo.o এবং বার.ও তৃতীয় অংশে a.out এর সাথে সংযুক্ত থাকে (যেমনটি সাধারণ) তবে সেই মোড়ক এটির একাধিক উদাহরণ প্রতিরোধ করে না, প্রতিটি বস্তু ফাইলে একটি করে।
ডেভিড কনরাড

সমস্যাটি যা এখানে #ifndef HEADER_Hপ্রতিরোধ করার কথা তা এখানে বর্ণিত নয় ?
রবার্ট হার্ভে

27

সি এবং সি ++ এক্ষেত্রে খুব একই রকম আচরণ করে - আপনার inlineশিরোনামে ফাংশন থাকতে পারে। C ++, কোনো পদ্ধতি যার শরীর বর্গ সংজ্ঞা ভিতরে পরোক্ষভাবে হয় inline। আপনি যদি সি তে একই কাজ করতে চান তবে ফাংশনগুলি ঘোষণা করুন static inline


" ফাংশনগুলি ঘোষণা করুনstatic inline " ... এবং আপনার এখনও প্রতিটি অনুবাদ ইউনিটে ফাংশনটির একাধিক অনুলিপি রয়েছে যা এটি ব্যবহার করে। অ + static inlineফাংশন সহ সি ++ এ আপনার কাছে কেবল একটি অনুলিপি থাকবে। সিটিতে শিরোনামে বাস্তবায়নটি পেতে, আপনাকে অবশ্যই 1) প্রয়োগটি চিহ্নিত করতে হবে inline(উদাঃ inline void func(){do_something();}), এবং 2) আসলে বলতে হবে যে এই ফাংশনটি কোনও বিশেষ অনুবাদ ইউনিটে থাকবে (যেমন void func();)।
রুশলান

6

শিরোনাম ফাইলের ধারণার জন্য একটু ব্যাখ্যা দরকার:

হয় আপনি সংকলকের কমান্ড লাইনে একটি ফাইল দিন বা একটি '# অন্তর্ভুক্ত' করুন। সংকলকগুলির বেশিরভাগই উত্স ফাইল হিসাবে এক্সটেনশন সি, সি, সিপিপি, সি ++ ইত্যাদি সহ একটি কমান্ড ফাইল গ্রহণ করে। যাইহোক, তারা সাধারণত কোনও উত্স ফাইলে যেকোন স্বেচ্ছাসেবক এক্সটেনশনের ব্যবহার সক্ষম করতে একটি কমান্ড-লাইন বিকল্প অন্তর্ভুক্ত করে।

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

প্রিপ্রোসেসর পদক্ষেপটি আসলে সেগুলি নেয় এবং সবকিছুই সংকলকটিতে একক বড় ফাইলের মতো প্রদর্শিত হয়। শিরোনামে বা উত্সটিতে যা ছিল তা এই মুহূর্তে প্রাসঙ্গিক নয়। সাধারণত একটি সংকলকের একটি বিকল্প থাকে যা এই পর্যায়ে আউটপুট প্রদর্শন করতে পারে।

তাই প্রতিটি ফাইল যা সংকলক কমান্ড লাইনে দেওয়া হয়েছিল তার জন্য একটি বিশাল ফাইল সংকলককে দেওয়া হয়। এটিতে কোড / ডেটা থাকতে পারে যা মেমরি দখল করবে এবং / অথবা অন্যান্য ফাইল থেকে রেফারেন্স হিসাবে একটি প্রতীক তৈরি করবে। এখন এগুলির প্রত্যেকটি একটি 'অবজেক্ট' চিত্র তৈরি করবে। লিঙ্কার একটি 'সদৃশ প্রতীক' দিতে পারে যদি একই চিহ্নটি দুটিরও বেশি অবজেক্ট ফাইলে পাওয়া যায় যা একত্রে লিঙ্ক করা হচ্ছে। সম্ভবত এটিই কারণ; এটি একটি হেডার ফাইলে কোড রাখার পরামর্শ দেওয়া হয়নি, যা বস্তু ফাইলে প্রতীক তৈরি করতে পারে।

'ইনলাইন' সাধারণত ইনলাইন করা হয় .. তবে ডিবাগ করার সময় সেগুলি ইনলাইন করা নাও হতে পারে। তাহলে লিঙ্কার কেন বহুগুণ সংজ্ঞায়িত ত্রুটি দেয় না? সরল ... এগুলি 'দুর্বল' প্রতীক এবং যতক্ষণ না সমস্ত বস্তু থেকে দুর্বল চিহ্নের জন্য সমস্ত ডেটা / কোড একই আকার এবং বিষয়বস্তু হয় ততক্ষণ লিঙ্কযুক্তগুলি অন্য অবজেক্টগুলি থেকে একটি অনুলিপি এবং ড্রপ অনুলিপি রাখবে। এটা কাজ করে।


3

আপনি সি 99 এ এটি করতে পারেন: inlineফাংশনগুলি অন্য কোথাও সরবরাহের গ্যারান্টিযুক্ত, সুতরাং যদি কোনও ফাংশনটি ইনলাইন না করা হত, তবে এর সংজ্ঞাটি ঘোষণায় অনুবাদ করা হয় (অর্থাত্ বাস্তবায়ন বাতিল করা হয়)। এবং, অবশ্যই, আপনি ব্যবহার করতে পারেন static


1

সি ++ স্ট্যান্ডার্ড কোট

সি ++ 17 N4659 মান খসড়া 10.1.6 "ইনলাইন সুনির্দিষ্টভাবে উল্লেখ করা" বলছেন যে পদ্ধতি পরোক্ষভাবে ইনলাইন আছেন:

4 ক্লাস সংজ্ঞা মধ্যে সংজ্ঞায়িত একটি ফাংশন একটি ইনলাইন ফাংশন।

এবং তারপর আরো নিচে, আমরা দেখতে যে ইনলাইন পদ্ধতি না শুধুমাত্র করতে পারেন, কিন্তু উচিত নয় সব অনুবাদ ইউনিটে সংজ্ঞায়িত করা:

An একটি অনূদিত ফাংশন বা পরিবর্তনশীল প্রতিটি অনুবাদ ইউনিটে সংজ্ঞায়িত করা হবে যেখানে এটি গন্ধযুক্ত-ব্যবহৃত হয় এবং প্রতিটি ক্ষেত্রে ঠিক একই সংজ্ঞা থাকবে (.2.২)।

এটি 12.2.1 "সদস্য কার্যাদি" তে একটি নোটে স্পষ্টভাবে উল্লেখ করা হয়েছে:

1 একটি সদস্য ফাংশনকে তার শ্রেণীর সংজ্ঞায় (১১.৪) সংজ্ঞায়িত করা যেতে পারে, যা ক্ষেত্রে এটি একটি ইনলাইন সদস্য ফাংশন (১০.১.)) [...]

3 [দ্রষ্টব্য: কোনও প্রোগ্রামে অন-ইনলাইন সদস্য ফাংশনের সর্বাধিক এক সংজ্ঞা থাকতে পারে। কোনও প্রোগ্রামে একাধিক ইনলাইন সদস্য ফাংশন সংজ্ঞা থাকতে পারে। 6.2 এবং 10.1.6 দেখুন। - শেষ নোট]

জিসিসি 8.3 বাস্তবায়ন

main.cpp

struct MyClass {
    void myMethod() {}
};

int main() {
    MyClass().myMethod();
}

প্রতীকগুলি সঙ্কলন এবং দেখুন:

g++ -c main.cpp
nm -C main.o

আউটপুট:

                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 W MyClass::myMethod()
                 U __stack_chk_fail
0000000000000000 T main

তারপরে আমরা দেখতে পাচ্ছি man nmযে MyClass::myMethodপ্রতীকটি ELF অবজেক্ট ফাইলগুলিতে দুর্বল হিসাবে চিহ্নিত হয়েছে, যা বোঝায় যে এটি একাধিক অবজেক্ট ফাইলগুলিতে প্রদর্শিত হতে পারে:

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


-4

সম্ভবত একই কারণে আপনাকে অবশ্যই জাভাতে শ্রেণি সংজ্ঞাটির ভিতরে সম্পূর্ণ পদ্ধতি প্রয়োগ করতে হবে।

স্কুইগ্লি ব্র্যাকেট এবং একই কীওয়ার্ডের অনেকগুলি সহ তারা এ জাতীয় দেখতে পারে তবে এগুলি ভিন্ন ভাষা।


1
না, আসলে একটি আসল উত্তর আছে, এবং সি ++ এর প্রাথমিক লক্ষ্যগুলির একটি সি এর সাথে পিছনে সামঞ্জস্যপূর্ণ ছিল
এড এস

4
না, এটি "সি সামঞ্জস্যতার একটি উচ্চ ডিগ্রি" এবং "সি এর সাথে কোনও নিরর্থক অসামঞ্জস্য নেই" ডিজাইন করা হয়েছিল। (উভয় স্ট্রাস্ট্রপ থেকে) আমি সম্মত হই যে এই নির্দিষ্ট অসঙ্গতিটি কেন উপযুক্ত নয় তা হাইলাইট করার জন্য আরও গভীরতর উত্তর দেওয়া যেতে পারে। এক সরবরাহ বিনামূল্যে মনে হয়।
পল কসাই

আমার কাছে থাকত তবে সাইমন রিখটার ইতিমধ্যে ছিলাম যখন আমি এটি পোস্ট করি। "পশ্চাদপটে সামঞ্জস্যপূর্ণ" এবং "সি সুসংগততার একটি উচ্চতর ডিগ্রি" এর মধ্যে পার্থক্যটি সম্পর্কে আমরা কাঁপতে পারি, তবে সত্য এই উত্তরটি ভুল রয়েছে। শেষের বিবৃতিটি সঠিক হবে যদি আমরা সি # এবং সি ++ তুলনা করি তবে সি এবং সি ++ এর সাথে তেমন কিছু না।
এড এস।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.