টেম্প্লেটেড সি ++ ক্লাসগুলিকে .hpp / .cpp ফাইলে বিভক্ত করা - এটি কি সম্ভব?


99

আমি একটি সি ++ টেম্পলেট শ্রেণি সংকলন করতে গিয়ে ত্রুটি পাচ্ছি যা একটি .hppএবং .cppফাইলের মধ্যে বিভক্ত :

$ g++ -c -o main.o main.cpp  
$ g++ -c -o stack.o stack.cpp   
$ g++ -o main main.o stack.o  
main.o: In function `main':  
main.cpp:(.text+0xe): undefined reference to 'stack<int>::stack()'  
main.cpp:(.text+0x1c): undefined reference to 'stack<int>::~stack()'  
collect2: ld returned 1 exit status  
make: *** [program] Error 1  

আমার কোডটি এখানে:

stack.hpp :

#ifndef _STACK_HPP
#define _STACK_HPP

template <typename Type>
class stack {
    public:
            stack();
            ~stack();
};
#endif

stack.cpp :

#include <iostream>
#include "stack.hpp"

template <typename Type> stack<Type>::stack() {
        std::cerr << "Hello, stack " << this << "!" << std::endl;
}

template <typename Type> stack<Type>::~stack() {
        std::cerr << "Goodbye, stack " << this << "." << std::endl;
}

main.cpp :

#include "stack.hpp"

int main() {
    stack<int> s;

    return 0;
}

ldঅবশ্যই সঠিক: প্রতীকগুলি মধ্যে নেই stack.o

আমি ইতিমধ্যে এটি যেমন বলেছি তেমন করায় এই প্রশ্নের উত্তর সাহায্য করবে না।
এটির সাহায্য হতে পারে তবে আমি প্রতিটি একক পদ্ধতিতে .hppফাইলটিতে যেতে চাই না — আমার উচিত ছিল না, আমার উচিত?

স্ট্যান্ড্যালোন অবজেক্ট ফাইল হিসাবে লিঙ্ক না করে কেবল কি সমস্ত কিছু .cppফাইলের মধ্যে ফাইলটিতে স্থানান্তরিত করার .hppএবং কেবল সবকিছু অন্তর্ভুক্ত করার একমাত্র যুক্তিসঙ্গত সমাধান ? ভীষণ কুৎসিত লাগে ! সেক্ষেত্রে আমি আমার আগের অবস্থায় ফিরে যেতে পারি এবং এর সাথে নাম পরিবর্তন stack.cppকরে stack.hppএটি করা হয়ে যেতে পারে।


আপনি যখন সত্যই আপনার কোডটি গোপন রাখতে চান (একটি বাইনারি ফাইলে) বা এটি পরিষ্কার রাখতে চান তার জন্য দুটি দুর্দান্ত কর্মক্ষেত্র রয়েছে। এটি প্রথম পরিস্থিতিতে হলেও সাধারণতা হ্রাস করা প্রয়োজন। : এটা এখানে ব্যাখ্যা করা হয় stackoverflow.com/questions/495021/...
Sheric

স্পষ্ট টেমপ্লেট ইনস্ট্যান্স কিভাবে আপনি টেমপ্লেট কম্পাইল সময় হ্রাস সম্পর্কে যেতে পারে: stackoverflow.com/questions/2351148/...
সিরো Santilli郝海东冠状病六四事件法轮功

উত্তর:


152

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

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

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

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

আমি আশা করি এই আলোচনা সহায়ক হবে।


4
"এটি অবশ্যই বুঝতে হবে যে টেম্পলেট শ্রেণি মোটেই একটি শ্রেণি নয়" - এটি অন্যভাবে নয় কি? ক্লাস টেম্পলেট একটি টেম্পলেট। "টেম্পলেট শ্রেণি" কখনও কখনও "কোনও টেম্পলেট ইনস্ট্যান্টেশন" এর জায়গায় ব্যবহৃত হয় এবং এটি একটি প্রকৃত শ্রেণি হবে।
Xupicor

কেবল রেফারেন্সের জন্য, কোনও কাজের ক্ষেত্র নেই তা বলা ঠিক নয়! পদ্ধতিগুলি থেকে ডেটা স্ট্রাকচারগুলি পৃথক করাও একটি খারাপ ধারণা কারণ এটি এনক্যাপসুলেশন দ্বারা বিরোধী। আছে: একটি দুর্দান্ত কার্যসংক্রান্ত আপনি কিছু পরিস্থিতিতে এখানে ব্যবহার করতে পারেন (আমি সবচেয়ে বিশ্বাস) এর stackoverflow.com/questions/495021/...
Sheric

@ এক্সপিকর, আপনি ঠিক বলেছেন। প্রযুক্তিগতভাবে "ক্লাস টেম্পলেট" আপনি যা লিখেন তাই আপনি কোনও "টেম্পলেট ক্লাস" এবং তার সম্পর্কিত বিষয়টিকে ইনস্ট্যান্ট করতে পারেন। তবে, আমি বিশ্বাস করি যে জেনেরিক পরিভাষায়, উভয় পদই আন্তঃবিস্মরণীয়ভাবে ব্যবহার করা সমস্ত ভুল হবে না, "ক্লাস টেম্পলেট" নিজেই সংজ্ঞায়নের জন্য বাক্য গঠনটি "টেম্পলেট" শব্দ দিয়ে শুরু হয়, "শ্রেণি" নয়।
শারজিথ এন।

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

এই কাজটি করার জন্য আমি সর্বাধিক নিকটতম জিনিসটি হ'ল .h / .hpp ফাইলগুলির একটি জোড়া ব্যবহার করা এবং আপনার টেম্পলেট শ্রেণীর সংজ্ঞা দেওয়া .h ফাইলের শেষে "ফাইলের নাম। Hpp" অন্তর্ভুক্ত করা। (সেমিকোলন সহ ক্লাস সংজ্ঞা জন্য আপনার বন্ধ বন্ধনী নীচে)। এটি অন্তত কাঠামোগতভাবে তাদের ফাইলওয়ালা আলাদা করে দেয় এবং অনুমোদিত হয় কারণ শেষ পর্যন্ত, সংকলকটি আপনার # অন্তর্ভুক্ত "ফাইলের নাম hpp" এর উপরে আপনার .hpp কোডটি অনুলিপি করে / আটকায়।
আর্টোরিয়াস 2718

90

এটি সম্ভব, যতক্ষণ আপনি জানেন আপনি কী ইনস্ট্যানটিশনের প্রয়োজন হচ্ছেন

Stack.cpp এর শেষে নীচের কোডটি যুক্ত করুন এবং এটি কাজ করবে:

template class stack<int>;

স্ট্যাকের সমস্ত অ-টেম্পলেট পদ্ধতিগুলি তাত্ক্ষণিকভাবে তৈরি করা হবে, এবং লিঙ্কিংয়ের ধাপটি দুর্দান্ত কাজ করবে।


7
অনুশীলনে, বেশিরভাগ লোকেরা এর জন্য একটি পৃথক সিপিপি ফাইল ব্যবহার করে - স্ট্যাকিনস্ট্যানটিশনস সিপিপি-র মতো কিছু।
নেমানজা ত্রিফুনোভিচ

@ নেমনজা ত্রিফুনোভিচ আপনি কি স্ট্যাকিনস্ট্যানেশনস সিপিপি দেখতে চান তার একটি উদাহরণ দিতে পারেন?
qwerty9967

4
প্রকৃতপক্ষে অন্যান্য সমাধান রয়েছে: কোডেপ্রজেক্ট
আর্টিকেল

@ বেনোতেট আমি একটি ত্রুটি ত্রুটি পেয়েছি: 'এর আগে অযোগ্য-আইডি প্রত্যাশিত; টোকেন টেমপ্লেট স্ট্যাক <int>; তুমি কি জানো কেন? ধন্যবাদ!
ক্যামিনো

4
আসলে, সঠিক বাক্য গঠনটি হ'ল template class stack<int>;
পল বাল্টেস্কু

8

আপনি এটি এইভাবে করতে পারেন

// xyz.h
#ifndef _XYZ_
#define _XYZ_

template <typename XYZTYPE>
class XYZ {
  //Class members declaration
};

#include "xyz.cpp"
#endif

//xyz.cpp
#ifdef _XYZ_
//Class definition goes here

#endif

এটি নিয়ে দানিউভে আলোচনা হয়েছে

এছাড়াও প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী কিন্তু সি ++ রপ্তানি শব্দ ব্যবহার করে।


4
includeএকটি cppফাইল আইং সাধারণত একটি ভয়ানক ধারণা। এমনকি যদি এর কোনও বৈধ কারণ আপনার কাছে রয়েছে তবে ফাইলটি - যা সত্যই কেবল মহিমান্বিত শিরোলেখ - একটি কী hppবা কিছু আলাদা এক্সটেনশন দেওয়া উচিত (উদাহরণস্বরূপ tpp) যা চলছে তা খুব স্পষ্ট করে দেওয়ার জন্য , আসল ফাইলগুলি makefileলক্ষ্য করে গুলি ইত্যাদির বিভ্রান্তি দূর করুন ইত্যাদি। cpp
আন্ডারস্কোর_ডে

@ আসরস্কোর_ডি আপনি ব্যাখ্যা করতে পারবেন কেন একটি .cppফাইল সহ একটি ভয়ংকর ধারণা?
আব্বাস

4
@ আব্বাস কারণ এক্সটেনশন cpp(বা cc, বা c, বা যাই হোক না কেন) ফাইলটি বাস্তবায়নের একটি অংশ, ফলাফল অনুবাদ ইউনিট (প্রিপ্রোসেসর আউটপুট) পৃথকভাবে সংকলনযোগ্য এবং ফাইলটির বিষয়বস্তু কেবল একবারই সংকলিত হয়েছে। এটি ইঙ্গিত দেয় না যে ফাইলটি ইন্টারফেসের একটি পুনরায় ব্যবহারযোগ্য অংশ, নির্বিচারে কোথাও অন্তর্ভুক্ত করা যায়। #includeএকটি আসল cpp ফাইল যুক্ত করা দ্রুত আপনার স্ক্রিনটি একাধিক সংজ্ঞা ত্রুটিতে পূরণ করবে এবং ঠিক তাই। এক্ষেত্রে যেমন এর কারণ রয়েছে #include, cppকেবলমাত্র তার এক্সটেনশনের ভুল পছন্দ ছিল।
আন্ডারস্কোর_ডি

@ আসরস্কোর_ডি তাই মূলত এ .cppজাতীয় ব্যবহারের জন্য এক্সটেনশনটি ব্যবহার করা ভুল । তবে অন্য একটি ব্যবহার .tppপুরোপুরি ঠিক আছে, যা একই উদ্দেশ্যে কাজ করবে তবে সহজে / দ্রুত বোঝার জন্য আলাদা এক্সটেনশন ব্যবহার করবে?
আব্বাস

4
@Abbas হ্যাঁ, cpp/ cc, / etc অবশ্যই এড়িয়ে চলতে হবে, কিন্তু এটা করার চেয়ে অন্য কিছু ব্যবহার একটি ভাল ধারণা hpp- যেমন tpp, tccইত্যাদি - আপনি ফাইলের নাম বাকি পুনঃব্যবহার এবং ইঙ্গিত করতে পারেন যাতে করে tppফাইল, যদিও এটি একটি হেডার মত কাজ করে, সংশ্লিষ্ট টেম্পলেট ঘোষণাগুলির বহির্মুখী প্রয়োগ করে hpp। সুতরাং এই পোস্টটি একটি ভাল ভিত্তি দিয়ে শুরু হয় - 2 টি পৃথক ফাইলে ঘোষণা এবং সংজ্ঞাগুলি পৃথক করে, যেগুলি ছাঁটাই / গ্রেপ করা সহজ হতে পারে বা কখনও কখনও বিজ্ঞপ্তি নির্ভরতা আইএমইয়ের কারণে প্রয়োজন হয় - তবে দ্বিতীয় ফাইলটির ভুল এক্সটেনশন রয়েছে বলে প্রস্তাব দিয়ে খারাপভাবে শেষ হয় ends
আন্ডারস্কোর_

6

না, এটা সম্ভব নয়। মূলশব্দ ব্যতীত নয় export, যা সমস্ত উদ্দেশ্য এবং উদ্দেশ্যে সত্যই বিদ্যমান নেই।

আপনি সবচেয়ে ভাল যা করতে পারেন তা হল আপনার ফাংশন বাস্তবায়নগুলি একটি ".tcc" বা ".tpp" ফাইলে রাখা এবং আপনার .hpp ফাইলটির শেষে .tcc ফাইল অন্তর্ভুক্ত করুন। তবে এটি নিছক প্রসাধনী; এটি এখনও শিরোনাম ফাইলগুলিতে সমস্ত বাস্তবায়নের সমান। এটি টেমপ্লেটগুলি ব্যবহারের জন্য কেবল মূল্য pay


4
আপনার উত্তরটি সঠিক নয়। আপনি কোন টেমপ্লেট আর্গুমেন্টটি ব্যবহার করবেন তা জানা থাকলে আপনি সিপিপি ফাইলে একটি টেম্পলেট শ্রেণি থেকে কোড তৈরি করতে পারেন। আরও তথ্যের জন্য আমার উত্তর দেখুন।
বেনোইট

4
সত্য, তবে এটি .cpp ফাইল আপডেট করার প্রয়োজন প্রতি গুরুতর সীমাবদ্ধতার সাথে আসে এবং প্রতিবার একটি নতুন ধরণের প্রবর্তিত হয় যা টেমপ্লেট ব্যবহার করে, যা সম্ভবত ওপি-র মনে ছিল না।
চার্লস সালভিয়া

3

শুধুমাত্র যদি আপনি #include "stack.cppশেষে stack.hpp। আমি কেবলমাত্র এই পদ্ধতির প্রস্তাব দিই যদি বাস্তবায়ন তুলনামূলকভাবে বড় হয় এবং যদি আপনি .cpp ফাইলটির নাম পরিবর্তন করে অন্য এক্সটেনশান হিসাবে নিয়মিত কোড থেকে আলাদা করতে পারেন।


4
যদি আপনি এটি করছেন, আপনি আপনার স্ট্যাক সিপিপি ফাইলে # স্বতন্ত্র STACK_CPP (এবং বন্ধুরা) যুক্ত করতে চাইবেন।
স্টিফেন নেওয়েল

এই পরামর্শ আমাকে মারধর। আমিও স্টাইলের কারণে এই পদ্ধতির পছন্দ করি না।
luke

4
হ্যাঁ, এই জাতীয় ক্ষেত্রে, ২ য় ফাইলটি অবশ্যই অবশ্যই এক্সটেনশন দেওয়া উচিত নয় cpp(বাcc বা যা কিছু হোক) কারণ এটি তার আসল ভূমিকার সম্পূর্ণ বিপরীত। পরিবর্তে এটির একটি আলাদা এক্সটেনশান দেওয়া উচিত যা এটি (এ) শিরোনাম এবং (খ) শিরোনামে অন্তর্ভুক্ত করা উচিত অন্য শিরোনামের নীচে জন্য একটি শিরোলেখ নির্দেশ করে। আমি ব্যবহার tppএই, যা handily এছাড়াও জন্য দাঁড়ানো করতে tই.এম. pপ্রয়াত তোমার দর্শন লগ করাp lementation (আউট-অফ-লাইন সংজ্ঞা)। আমি এখানে এই সম্পর্কে আরও র‌্যাম্বল করেছি
আন্ডারস্কোর_২_

3

আমি বিশ্বাস করি যে একটি শিরোনাম এবং সিপিসিতে টেম্প্লেটেড কোড আলাদা করার চেষ্টা করার দুটি মূল কারণ রয়েছে:

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

অন্যান্য হ'ল সংকলন বার হ্রাস।

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

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


2

কখনও কখনও সিপিপি ফাইলে বেশিরভাগ বাস্তবায়ন গোপন করা সম্ভব হয়, যদি আপনি অ সাধারণ টেম্পলেট প্যারামিটারগুলি অ-টেম্পলেট শ্রেণিতে (সম্ভবত টাইপ-অনিরাপদ) থেকে নিষ্ক্রিয় করতে পারেন তবে সাধারণ কার্যকারিতা ফুটিয়ে তুলতে পারেন। তারপরে শিরোনামে সেই শ্রেণিতে পুনঃনির্দেশ কল থাকবে। "টেমপ্লেট ব্লাট" সমস্যার সাথে লড়াই করার সময় অনুরূপ পদ্ধতির ব্যবহার করা হয়।


+1 - যদিও বেশিরভাগ সময় এটি খুব ভালভাবে কাজ করে না (কমপক্ষে, আমার
ইচ্ছামতো

2

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

এগুলি ডিএলএল (!) জুড়ে রফতানি করাও সম্ভব তবে সিনট্যাক্সটি ডান (__declspec (dllexport) এবং রফতান কীওয়ার্ড) এর এমএস-নির্দিষ্ট সংমিশ্রণগুলি পাওয়া বেশ জটিল।

আমরা এটি একটি গণিত / জিওম লাইব ব্যবহার করেছি যা ডাবল / ফ্লোটকে প্ররোচিত করে, তবে বেশ প্রচুর কোড ছিল। (আমি এটির জন্য প্রায় সময় ধরে গুগল করেছিলাম, যদিও আজ সেই কোডটি নেই))


2

সমস্যাটি হ'ল কোনও টেমপ্লেটটি একটি আসল বর্গ তৈরি করে না, এটি কেবল একটি টেম্পলেট যা সংকলককে বর্গ তৈরি করতে হয় তা বলছে telling আপনার একটি কংক্রিট শ্রেণি তৈরি করা দরকার।

সহজ এবং প্রাকৃতিক উপায় হ্যাডার ফাইলটিতে পদ্ধতিগুলি রাখা to তবে আরও একটি উপায় আছে।

আপনার .cpp ফাইলে, আপনার যদি প্রতিটি টেম্পলেট ইনস্ট্যান্টেশন এবং প্রয়োজনীয় পদ্ধতির একটি রেফারেন্স থাকে তবে সংকলকটি আপনার প্রকল্পের জন্য ব্যবহারের জন্য সেখানে সেগুলি উত্পন্ন করবে।

নতুন stack.cpp:

#include <iostream>
#include "stack.hpp"
template <typename Type> stack<Type>::stack() {
        std::cerr << "Hello, stack " << this << "!" << std::endl;
}
template <typename Type> stack<Type>::~stack() {
        std::cerr << "Goodbye, stack " << this << "." << std::endl;
}
static void DummyFunc() {
    static stack<int> stack_int;  // generates the constructor and destructor code
    // ... any other method invocations need to go here to produce the method code
}

8
আপনার ডামে ফাংশন দরকার নেই: 'টেম্পলেট স্ট্যাক <int> ব্যবহার করুন;' এটি বর্তমান সংকলন ইউনিটে টেমপ্লেটের একটি ইনস্ট্যান্সেশনকে বাধ্য করে। খুব কার্যকর যদি আপনি কোনও টেমপ্লেট সংজ্ঞায়িত করেন তবে কেবলমাত্র একটি ভাগ করা bষুধে নির্দিষ্ট কয়েকটি বাস্তবায়ন চান implement
মার্টিন ইয়র্ক

@ মার্টিন: সমস্ত সদস্যের কাজ সহ? সেটা চমৎকার. আপনার এই পরামর্শটি "লুকানো সি ++ বৈশিষ্ট্যগুলি" থ্রেডে যুক্ত করা উচিত।
মার্ক র্যানসোম

@ লোকি অস্টারি আমি এই বিষয়ে একটি নিবন্ধ পেয়েছি যে কেউ যদি আরও শিখতে চায়: cplusplus.com/forum/articles/14272
অ্যান্ড্রু লারসন

1

আপনার এইচপিপি ফাইলের সবকিছু থাকা দরকার। সমস্যাটি হ'ল ক্লাসগুলি প্রকৃতপক্ষে তৈরি হয় না যতক্ষণ না সংকলকটি দেখে না যে সেগুলি অন্য কোনও সিপিপি ফাইলের প্রয়োজন so তাই এতে টেম্প্লেটেড ক্লাসটি সংকলনের জন্য সমস্ত কোড উপলব্ধ থাকতে হবে।

একটি জিনিস যা আমি করতে চাই তা হ'ল আমার টেম্পলেটগুলিকে জেনেরিক অ-টেম্প্লেটেড অংশে (যা সিপিপি / এইচপিপি মধ্যে বিভক্ত করা যেতে পারে) এবং টাইপ-নির্দিষ্ট টেম্পলেট অংশ যা অ-টেম্প্লেটেড শ্রেণীর উত্তরাধিকার সূত্রে ভাগ করে দেয় split


1

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

কিছু দরকারী তথ্য এখানে রয়েছে: https://docs.microsoft.com/en-us/cpp/cpp/explicit-instantiation?view=vs-2019

আপনার একই উদাহরণের জন্য: Stack.hpp

template <class T>
class Stack {

public:
    Stack();
    ~Stack();
    void Push(T val);
    T Pop();
private:
    T val;
};


template class Stack<int>;

stack.cpp

#include <iostream>
#include "Stack.hpp"
using namespace std;

template<class T>
void Stack<T>::Push(T val) {
    cout << "Pushing Value " << endl;
    this->val = val;
}

template<class T>
T Stack<T>::Pop() {
    cout << "Popping Value " << endl;
    return this->val;
}

template <class T> Stack<T>::Stack() {
    cout << "Construct Stack " << this << endl;
}

template <class T> Stack<T>::~Stack() {
    cout << "Destruct Stack " << this << endl;
}

main.cpp

#include <iostream>
using namespace std;

#include "Stack.hpp"

int main() {
    Stack<int> s;
    s.Push(10);
    cout << s.Pop() << endl;
    return 0;
}

আউটপুট:

> Construct Stack 000000AAC012F8B4
> Pushing Value
> Popping Value
> 10
> Destruct Stack 000000AAC012F8B4

তবে তবে আমি এই পদ্ধতির সম্পূর্ণ পছন্দ করি না, কারণ এটি অ্যাপ্লিকেশনটি টেম্প্লেটেড শ্রেণিতে ভুল ডেটাটাইপগুলি পাস করে নিজেকে পাদদেশে গুলি করতে দেয়। উদাহরণস্বরূপ, মূল ফাংশনে, আপনি অন্য ধরণের পাস করতে পারেন যা স্পষ্টভাবে এস.পুষ্প (1.2) এর মত ইনট এ রূপান্তরিত হতে পারে; এবং এটা আমার মতে খারাপ।


স্পষ্ট টেমপ্লেট ইনস্ট্যান্স নির্দিষ্ট প্রশ্ন: stackoverflow.com/questions/2351148/...
সিরো Santilli郝海东冠状病六四事件法轮功

0

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


0

আরেকটি সম্ভাবনা হ'ল এরকম কিছু করা:

#ifndef _STACK_HPP
#define _STACK_HPP

template <typename Type>
class stack {
    public:
            stack();
            ~stack();
};

#include "stack.cpp"  // Note the include.  The inclusion
                      // of stack.h in stack.cpp must be 
                      // removed to avoid a circular include.

#endif

শৈলীর বিষয় হিসাবে আমি এই পরামর্শটি অপছন্দ করি তবে এটি আপনার পক্ষে উপযুক্ত হতে পারে।


4
মহিমান্বিত ২ য় শিরোনাম অন্তর্ভুক্ত হওয়ার cppসাথে প্রকৃত উত্স ফাইলগুলির সাথে বিভ্রান্তি এড়াতে কমপক্ষে অন্য কোনও এক্সটেনশন থাকা উচিত । সাধারণ পরামর্শ অন্তর্ভুক্ত tppএবং tcc
আন্ডারস্কোর_ডে

0

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


4
এটি প্রায় একটি লিঙ্ক-কেবল উত্তর, এবং সেই লিঙ্কটি মারা গেছে।
আন্ডারস্কোর_ডি

0

1) .h এবং .cpp ফাইলগুলি পৃথক করার মূল কারণটি মনে রাখুন শ্রেণি প্রয়োগটি একটি পৃথক-সংকলিত ওবজ কোড হিসাবে আড়াল করা যা ব্যবহারকারীর কোডের সাথে লিখিত হতে পারে যা ক্লাসের একটি। এইচ অন্তর্ভুক্ত করে।

2) নন-টেম্পলেট ক্লাসে সমস্ত ভেরিয়েবলগুলি দৃ .়ভাবে এবং .h এবং .cpp ফাইলে নির্দিষ্ট করে সংজ্ঞায়িত করা হয়। সংকলক / সংকলন করার আগে ক্লাসে ব্যবহৃত সমস্ত ডেটা ধরণের সম্পর্কে প্রয়োজনীয় তথ্য থাকবে the অবজেক্ট / মেশিন কোড উত্পন্ন করার জন্য টেমপ্লেট ক্লাসগুলির নির্দিষ্ট তথ্য প্রকারের কোনও তথ্য নেই শ্রেণীর ব্যবহারকারী প্রয়োজনীয় তথ্য পাস করে কোনও বস্তুর ইনস্ট্যান্ট করার আগে প্রকার:

        TClass<int> myObj;

3) কেবলমাত্র এই তাত্ক্ষণিকতার পরে, সংস্থাপক উত্তীর্ণ ডেটা (গুলি) মেলানোর জন্য টেম্পলেট শ্রেণীর নির্দিষ্ট সংস্করণ তৈরি করে।

৪) অতএব, .cpp ব্যবহারকারীদের নির্দিষ্ট ডেটা টাইপ না জেনে আলাদাভাবে সংকলন করা যায় না। সুতরাং এটির জন্য ".h" এর মধ্যে সোর্স কোড হিসাবে থাকতে হবে যতক্ষণ না ব্যবহারকারী প্রয়োজনীয় ডেটা টাইপ নির্দিষ্ট করে না দেয়, এটি সংকলিত একটি নির্দিষ্ট ডেটা টাইপে উত্পন্ন করা যায়


-3

আমি ভিজুয়াল স্টুডিও 2010 এর সাথে কাজ করছি, যদি আপনি নিজের ফাইলগুলি .h এবং .cpp এ ভাগ করতে চান তবে .h ফাইলের শেষে আপনার সিপিপি শিরোনামটি অন্তর্ভুক্ত করুন

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