সি ++ এর সাথে কোডিং করার সময় পয়েন্টারগুলিকে কেন সুপারিশ করা হয় না?


45

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


40
"কোথাও" লিঙ্ক করুন। প্রসঙ্গটি খুব প্রাসঙ্গিক হতে পারে।

1
এই প্রশ্নটি আপনার জন্য আশাবাদী কার্যকর।
গ্রেট ক্লোবর্ন

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

1
@ ডঙ্কের মন্তব্যে যোগ করা, কখনও কখনও উচ্চ স্তরের ভাষাগুলিতে অন্তর্নির্মিত আবর্জনা সংগ্রহকারীরা ঠিক কাজ করেন না। অ্যাকশনস্ক্রিপ্ট 3 এর আবর্জনা সংগ্রহকারী, উদাহরণস্বরূপ না। এখনই এটিতে একটি ত্রুটি রয়েছে NetConnectionযা সার্ভারের সাথে সংযোগ বিচ্ছিন্ন করার ঘটনাগুলি ( স্ট্যাকওভারফ্লো / প্রশ্ন / 14780456/… ), পাশাপাশি কোনও প্রোগ্রামে একাধিক অবজেক্ট রয়েছে এমন একটি সমস্যা রয়েছে যা এটি নির্দিষ্টভাবে সংগ্রহ করতে অস্বীকার করবে will ...
Panzercrisis

... ( অ্যাডোব.ডেবনেট / আপত্তি স্ক্রিপ্ট / বিসর্জন / 3৩- ফান্ডামেন্টালস_ … - অনুসন্ধান করুন GCRoots are never garbage collected.এবং অনুচ্ছেদটি শুরু করেছেন The MMgc is considered a conservative collector for mark/sweep.)। প্রযুক্তিগতভাবে এটি অ্যাডোব ভার্চুয়াল মেশিন 2-এ, নিজেই এএস 3 নয়, তবে সমস্যাটি যখন উচ্চ স্তরের ভাষাগুলিতে, যা আবশ্যকভাবে আবর্জনা সংগ্রহের ক্ষেত্রে তৈরি হয়, তখন আপনার প্রায়শই ভাষার মধ্যে কোনও সত্যিকারের ডিবাগ করার উপায় নেই don't এই সমস্যাগুলি পুরোপুরি প্রোগ্রামের বাইরে। ...
Panzercrisis

উত্তর:


58

আমি মনে করি তাদের অর্থ নিয়মিত পয়েন্টারগুলির পরিবর্তে আপনার স্মার্ট পয়েন্টার ব্যবহার করা উচিত ।

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

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

সি ++ তে জঞ্জাল সংগ্রহ এবং মেমরি ফাঁস প্রতিরোধের উপর জোর দেওয়া হবে (কেবল দুটি নাম রাখার জন্য)। পয়েন্টারগুলি ভাষার একটি মৌলিক অঙ্গ, সুতরাং এগুলি ব্যবহার না করা প্রোগ্রামের সর্বাধিক ট্রিওয়াল ব্যতীত বেশ অসম্ভব।


22
সাধারণত শাস্ত্রীয় অর্থে এটি কঠোরভাবে আবর্জনা সংগ্রহ নয়, আরও রেফারেন্স গণনা। কমপক্ষে স্মার্ট পিটিআরটিতে আমি অভ্যস্ত ([বুস্ট | স্টাডি] :: শেয়ার্ড_পিটার)
ডগ টি।

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

3
সাধারণভাবে RAII।
ক্লাইম

3
না, এটি বোঝানো কী নয়। এটি শুধুমাত্র একটি দিক, এবং সবচেয়ে গুরুত্বপূর্ণ এক নয়।
কনরাড রুডল্ফ

আমি মনে করি স্মার্ট পয়েন্টারগুলি সবচেয়ে গুরুত্বপূর্ণ দিক, তবে আমি সম্মত হই যে আরও অনেকগুলি রয়েছে।
ডেড এমএমজি

97

যেহেতু আমিই পোলিমিকটি প্রকাশ করেছি তিনি "চ * সিঙ্কিং পয়েন্টার ব্যবহার করবেন না" আমার মনে হয় আমার এখানে মন্তব্য করা উচিত।

প্রথমত, একটি মেরুক হিসাবে এটি স্পষ্টতই একটি চরম দৃষ্টিভঙ্গি উপস্থাপন করে। সেখানে হয় স্পষ্টভাবে (কাঁচা) পয়েন্টার বৈধ ব্যবহারের। তবে আমি (এবং অনেক পেশাদার সি ++ প্রোগ্রামার) বজায় রেখেছি যে এই কেসগুলি অত্যন্ত বিরল। তবে আমরা যা বলতে চাইছি তা হ'ল:

প্রথম:

কাঁচা পয়েন্টার অবশ্যই কোনও পরিস্থিতিতে নিজের মেমরির নয়।

এখানে, "নিজস্ব স্মৃতি" এর অর্থ deleteহ'ল কোনও সময় সেই পয়েন্টারে ডাকা হয় (তবে এটি এর চেয়ে সাধারণ। এই বিবৃতিটি নিরাপদে নিরঙ্কুশ হিসাবে নেওয়া যেতে পারে। শুধুমাত্র যখন আপনার নিজের স্মার্ট পয়েন্টার (অথবা অন্যান্য মেমরি ব্যবস্থাপনা কৌশল) বাস্তবায়ন ব্যতিক্রম নয়। এবং এমনকি সেখানে সাধারণত আপনার এখনও নিম্ন স্তরে একটি স্মার্ট পয়েন্টার ব্যবহার করা উচিত ।

এর পক্ষে যুক্তিটি বেশ সহজ: কাঁচা পয়েন্টার যা নিজের মেমরির ত্রুটির উত্স প্রবর্তন করে। এবং এই ত্রুটিগুলি বিদ্যমান সফ্টওয়্যারগুলিতে বিস্তৃত: মেমরি ফাঁস এবং ডাবল মুছে ফেলা - উভয়ই অস্পষ্ট সম্পদের মালিকানার সরাসরি পরিণতি (তবে বিপরীত দিকে যাচ্ছে)।

কাঁচা পয়েন্টারগুলির পরিবর্তে কেবল স্মার্ট পয়েন্টার ব্যবহার করে এই সমস্যাটি পুরোপুরি বিনা মূল্যে নির্মূল করা যেতে পারে (সতর্কতা: এটি এখনও চিন্তাভাবনা প্রয়োজন, অবশ্যই ভাগ করা পয়েন্টারগুলি চক্রের দিকে পরিচালিত করতে পারে এবং এভাবে আবার স্মৃতি ফাঁস হতে পারে - তবে এটি সহজেই পরিহার্য)।

দ্বিতীয়ত:

সি ++ এর পয়েন্টারগুলির বেশিরভাগ ব্যবহার অপ্রয়োজনীয়।

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

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

এমন কারো জন্য যিনি আধুনিক সি ত জানেন ++ এটা পরিষ্কার যে আপনার খুব কমই প্রয়োজন কোনো পয়েন্টার (হয় স্মার্ট অথবা কাঁচা; ব্যতীত যখন iterators তাদের ব্যবহার করে)। ফলাফল কোডটি খাটো, কম জটিল, আরও পঠনযোগ্য, প্রায়শই আরও দক্ষ এবং আরও নির্ভরযোগ্য reliable


5
দীর্ঘশ্বাস ত্যাগ করুন ... এটি 30+ টির বেশি উত্তর সহ সত্যই উত্তর হওয়া উচিত ... বিশেষত দ্বিতীয় দফার জন্য। পয়েন্টারগুলি আধুনিক সি ++ এ খুব কমই প্রয়োজনীয়
চার্লস সালভিয়া

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

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

1
@ ভিএফ 1 std::unique_ptr। এছাড়াও, কেন না ptr_vec? তবে সাধারণত একটি মান ভেক্টর এখনও দ্রুত অদলবদল করবে (বিশেষত স্থানান্তরের শব্দার্থিক সহ)।
কনরাড রুডল্ফ

1
@gaazkam কেউ আপনাকে কেবল স্ট্যান্ডার্ড পাত্রে ব্যবহার করতে বাধ্য করেনি। উদাহরণস্বরূপ বুস্টের অসম্পূর্ণ প্রকারের জন্য সমর্থন সহ একটি মানচিত্রের প্রয়োগ রয়েছে। আর একটি সমাধান হ'ল টাইপ ইরেজর ব্যবহার করা; boost::variantএকটি recursive_wrapperসাথে সম্ভবত আমার প্রিয় সমাধান হ'ল একটি ডিএজি প্রতিনিধিত্ব করতে।
কনরাড রুডলফ

15

কেবলমাত্র আপনার কাছে এমন বিমূর্ততা উপলব্ধ রয়েছে যা পয়েন্টার ব্যবহারের আরও স্বভাবগত দিকগুলি যেমন: কাঁচা স্মৃতিতে অ্যাক্সেস পাওয়া এবং আপনার বরাদ্দের পরে পরিষ্কার করার মতো গোপন করে hide RAII এর মতো স্মার্ট পয়েন্টার, ধারক ক্লাস এবং নকশার ধরণগুলির সাহায্যে কাঁচা পয়েন্টার ব্যবহারের প্রয়োজনীয়তা হ্রাস পাচ্ছে। এটি বলেছিল, যে কোনও বিমূর্ততার মতো, আপনার বুঝতে হবে যে এগুলি আসলে কীভাবে তাদের বাইরে চলে যাওয়ার আগে কাজ করে।


11

তুলনামূলকভাবে সহজভাবে, সি মানসিকতা হ'ল "একটি সমস্যা পেয়েছেন? পয়েন্টার ব্যবহার করুন"। আপনি এটি সি স্ট্রিং, ফাংশন পয়েন্টার, পয়েন্টার-এ-ইয়েটারেটর, পয়েন্টার-টু-পয়েন্টার, অকার্যকর পয়েন্টার- এমনকি সদস্য পয়েন্টার সহ সি ++ এর প্রথম দিনগুলিতে দেখতে পাবেন।

তবে সি ++ এ আপনি অনেকগুলি বা এই সমস্ত কাজের জন্য মানগুলি ব্যবহার করতে পারেন। একটি ফাংশন বিমূর্ততা প্রয়োজন? std::function। এটি একটি মূল্য যা একটি ফাংশন। std::string? এটি একটি মান, এটি একটি স্ট্রিং। আপনি পুরো সি ++ জুড়ে একই ধরণের পন্থা দেখতে পাবেন। কোড এবং বিশ্লেষক উভয়ের জন্যই কোডটি বিশ্লেষণ করা সহজতর হয়েছে।


সি ++ এ: সমস্যা আছে? একটি পয়েন্টার ব্যবহার করুন। এখন আপনার 2 টি সমস্যা আছে ...
ড্যানিয়েল জাজুলা

10

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

সঠিক উদ্দেশ্যে কোনও সরঞ্জাম নির্বাচন কোডকে সহজ এবং অভিপ্রায়কে আরও দৃশ্যমান করে তোলে - পুনরাবৃত্তির জন্য পুনরাবৃত্তিকারী, জীবনকালীন পরিচালনার জন্য স্মার্ট পয়েন্টার ইত্যাদি etc.


3

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


2

@Jmquigley পয়েন্টার এবং পয়েন্টার গাণিতিক দ্বারা বর্ণিত মেমরি ফাঁসের ঝুঁকির পাশাপাশি সমস্যাগুলি বিবেচনা করা যেতে পারে কারণ পয়েন্টারগুলি স্মৃতিতে সর্বত্র নির্দেশ করতে পারে "বাগগুলি খুঁজে পাওয়া শক্ত" এবং "সুরক্ষা দুর্বলতা" তৈরি করে।

এ কারণেই তারা সি # এবং জাভাতে প্রায় পরিত্যক্ত ছিল।


আশা করুন যে তারা সি # তে "আটকানো" ছিলেন না। এই উত্তরটি দরিদ্র, ভয়ঙ্কর বানান রয়েছে এবং একটি ভয়ঙ্কর ভুল বিবৃতি রয়েছে।
রামহাউন্ড

1
তারা প্রায় পরিত্যক্ত ছিল। নেটিভ স্পিকারকে মৌমাছি না দেওয়ার জন্য আমি ক্ষমা চাই।
k3b

1
আরে, আমরা বানানটি সাহায্য করতে পারি। আপনি আশা বা বাদে বলতে চাচ্ছেন?
বিকাশকারীরা

1
প্রায় সি # তে পরিত্যাজ্য, আপনি এখনও unsafeকীওয়ার্ড নির্দিষ্ট করে পয়েন্টারটি সক্ষম করতে পারেন

-1

সি ++ বেশিরভাগ সি , বৈশিষ্ট্যগুলি এবং আরও অবজেক্ট এবং ক্লাস সমর্থন করে। সি ইতিমধ্যে পয়েন্টার এবং অন্যান্য স্টাফ ছিল।

পয়েন্টারগুলি একটি খুব কার্যকর কৌশল, যা অবজেক্ট ওরিয়েন্টেশনের সাথে একত্রিত হতে পারে এবং সি ++ তাদের সমর্থন করে। তবে, এই কৌশলটি শেখানো কঠিন এবং বুঝতে অসুবিধা এবং এটি খুব সহজেই অযাচিত ত্রুটিগুলি ঘটায় cause

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

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

অন্যান্য বিকাশকারীদের ভিন্ন মতামত থাকতে পারে। তবে, আমি ছাত্র এবং প্রোগ্রামাররা কীভাবে তা শিখতে পরামর্শ দিই:

(1) অবজেক্ট ছাড়া পয়েন্টার ব্যবহার করুন

(2) পয়েন্টার ছাড়াই অবজেক্ট

(3) অবজেক্টের স্পষ্ট পয়েন্টার

(4) অবজেক্টগুলিতে "লুকানো" পয়েন্টার (একে একে রেফারেন্স ) ;-)

সেই জন্য.

এমনকি যদি শেখানো কঠিন, এবং শেখাও কঠিন। এই লক্ষ্যগুলির জন্য অবজেক্ট পাস্কাল (ডেল্ফি, ফ্রিপ্যাসাল, অন্যান্য) এবং C++(জাভা বা সি # নয়) ব্যবহার করা যেতে পারে।

এবং, পরে নবজাতক প্রোগ্রামাররা প্রোগ্রামিং ভাষায় "জাভাস, সি #, অবজেক্ট ওরিয়েন্টেড পিএইচপি, এবং অন্যান্যগুলির মতো" লুকানো পয়েন্টারগুলিকে "অবজেক্টগুলিতে স্থানান্তর করতে পারে।


19
সি ++ "সি ক্লাস উইথ ক্লাস" এর চেয়ে অনেক বেশি।
ডেভিড থর্নলি

আপনি কেন সি ++ এবং সি এয়ার কোটে মুড়ে রাখছেন? এবং "লুকানো", "রেফারেন্স" এবং সব কিছুর? আপনি কি একজন "বিক্রয়কর্মী" এবং "প্রোগ্রামিং" তে অংশ নিচ্ছেন না?
ফ্রেসেল

আমি তাদের সাহসী করা উচিত।
উক্তি

-6

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

উদাহরণ:

class MyClass1 {
    public:
        void A (void);
        void B (void);
        void C (void);
    private:
        DWORD dwclass;
};

class MyClass2 {
    public:
        int C (int i);
};

void MyClass1::A (void) {
    MyClass2 *myclass= new MyClass2;
    dwclass=(DWORD)myclass;
}

void MyClass1::B (void) {
    MyClass2 *myclass= (MyClass2 *)dwclass;
    int i = myclass->C(0); // or int i=((MyClass2 *)dwclass)->C(0);
}

void MyClass1::B (void) {
    MyClass2 *myclass= (MyClass2 *)dwclass;
    delete myclass;
}

মূল কোডটির খুব সামান্য অংশ সম্পাদনা করুন। CSRecodset শ্রেণিটি কেবলমাত্র CXdbRecordset এর একটি কাস্টিং ক্লাস, যেখানে সমস্ত আসল কোড। এটি করার মাধ্যমে আমি ব্যবহারকারীকে আমার অধিকারগুলি হারা না করে আমি যা লিখেছিলাম তার সুবিধা নিতে পারি। আমি দেখানোর ভান করি না যে আমার ডাটাবেস ইঞ্জিনটি পেশাদার তবে এটি কার্যকরভাবে কাজ করে।

//-------------------------------------
class CSRecordSet : public CSObject
//-------------------------------------
{
public:
    CSRecordSet();
    virtual ~CSRecordSet();
    // Constructor
    bool Create(CSDataBase* pDataBase,CSQueryDef* pQueryDef);
    //Open, find, close
    int OpenRst(bool bReadBlanks=0,bool bCheckLastSql=0,bool bForceLoad=0,bool bMessage=1);     // for a given SQL
    int FindRecord(bool bNext);         // for a given SQL
    // TABLE must be ordered by the same fields that will be seek
    bool SeekRecord(int nFieldIndex, char *key, int length=0);  // CRT bsearch
    bool SeekRecord(int nFieldIndex, long key);     
    bool SeekRecord(int nFieldIndex, double key, int decimals);     
    bool SeekRecord(XSEK *SEK);     
    bool DeleteRecord(void);
    bool Close(void);
    // Record Position:
    bool IsEOF(void);           // pointer out of bound
    bool IsLAST(void);          // TRUE if last record
    bool IsBOF(void);           // pointer out of bound
    bool IsOpen(void);
    bool Move(long lRows);      // returns FALSE if out of bound
    void MoveNextNotEof(void);  // eof is tested
    void MoveNext(void);        // eof is not tested
    void MovePrev(void);        // bof is tested
    void MoveLast(void);
    void MoveFirst(void);
    void SetAbsolutePosition(long lRows);
    long GetAbsolutePosition(void);
    void GoToLast(void); // Restore position after a Filter
    // Table info
    long GetRecordCount(void);
    int GetRstTableNumber(void);
    int GetRecordLength(void); //includes stamp (sizeof char)
    int GetTableType(void);
    // Field info
    int GetFieldCount(void);
    void GetFieldName(int nFieldIndex, char *pbuffer);
    int GetFieldIndex(const char *sFieldName);
    int GetFieldSize(int nFieldIndex);
    int GetFieldDGSize(int nFieldIndex); // String size (i.e. dg_Boolean)
    long GetRecordID(void);
    int GetStandardFieldCount(void);
    bool IsMemoFileTable(void);
    bool IsNumberField(int nFieldIndex);
    int GetFieldType(int nFieldIndex);
    // Read Field value
    bool GetFieldValue(int nFieldIndex, XdbVar& var);
    bool GetFieldValueIntoBuffer(int nFieldIndex,char *pbuffer);
    char *GetMemoField(int nMemoFieldIndex, char *pbuffer, int buf_size);
    bool GetBinaryField(unsigned char *buffer,long *buf_size);
    // Write Field value
    void Edit(void); // required
    bool SetFieldValue(int nFieldIndex, XdbVar& var);
    bool SetFieldValueFromBuffer(int nFieldIndex,const char *pbuffer);
    bool Update(void); // required
    // pointer to the same lpSql
    LPXSQL GetSQL(void);
};

//---------------------------------------------------
CSRecordSet::CSRecordSet(){
//---------------------------------------------------
    pClass |= (CS_bAttach);
}
CSRecordSet::~CSRecordSet(){
    if(pObject) delete (CXdbRecordset*)pObject;
}
bool CSRecordSet::Create(CSDataBase* pDataBase,CSQueryDef* pQueryDef){
    CXdbQueryDef *qr=(CXdbQueryDef*)pQueryDef->GetObject();
    CXdbTables *db=(CXdbTables*)pDataBase->GetObject();
    CXdbRecordset *rst = new CXdbRecordset(db,qr);
    if(rst==NULL) return 0;
    pObject = (unsigned long) rst;
    return 1;
}
bool CSRecordSet::Close(void){
    return ((CXdbRecordset*)pObject)->Close();
}
int CSRecordSet::OpenRst(bool bReadBlanks,bool bCheckLastSql,bool bForceLoad, bool bMessage){
    unsigned long dw=0L;
    if(bReadBlanks) dw|=SQL_bReadBlanks;
    if(bCheckLastSql) dw|=SQL_bCheckLastSql;
    if(bMessage) dw|=SQL_bRstMessage;
    if(bForceLoad) dw|=SQL_bForceLoad;

    return ((CXdbRecordset*)pObject)->OpenEx(dw);
}
int CSRecordSet::FindRecord(bool bNext){
    return ((CXdbRecordset*)pObject)->FindRecordEx(bNext);
}
bool CSRecordSet::DeleteRecord(void){
    return ((CXdbRecordset*)pObject)->DeleteEx();
}
bool CSRecordSet::IsEOF(void){
    return ((CXdbRecordset*)pObject)->IsEOF();
}
bool CSRecordSet::IsLAST(void){
    return ((CXdbRecordset*)pObject)->IsLAST();
}
bool CSRecordSet::IsBOF(void){
    return ((CXdbRecordset*)pObject)->IsBOF();
}
bool CSRecordSet::IsOpen(void){
    return ((CXdbRecordset*)pObject)->IsOpen();
}
bool CSRecordSet::Move(long lRows){
    return ((CXdbRecordset*)pObject)->MoveEx(lRows);
}
void CSRecordSet::MoveNextNotEof(void){
    ((CXdbRecordset*)pObject)->MoveNextNotEof();
}
void CSRecordSet::MoveNext(void){
    ((CXdbRecordset*)pObject)->MoveNext();
}
void CSRecordSet::MovePrev(void){
    ((CXdbRecordset*)pObject)->MovePrev();
}
void CSRecordSet::MoveLast(void){
    ((CXdbRecordset*)pObject)->MoveLast();
}
void CSRecordSet::MoveFirst(void){
    ((CXdbRecordset*)pObject)->MoveFirst();
}
void CSRecordSet::SetAbsolutePosition(long lRows){
    ((CXdbRecordset*)pObject)->SetAbsolutePosition(lRows);
}
long CSRecordSet::GetAbsolutePosition(void){
    return ((CXdbRecordset*)pObject)->m_AbsolutePosition;
}
long CSRecordSet::GetRecordCount(void){
    return ((CXdbRecordset*)pObject)->GetRecordCount();
}
int CSRecordSet::GetFieldCount(void){
    return ((CXdbRecordset*)pObject)->GetFieldCount();
}
int CSRecordSet::GetRstTableNumber(void){
    return ((CXdbRecordset*)pObject)->GetRstTableNumber();
}
void CSRecordSet::GetFieldName(int nFieldIndex, char *pbuffer){
    ((CXdbRecordset*)pObject)->GetFieldName(nFieldIndex,pbuffer);
}
int CSRecordSet::GetFieldIndex(const char *sFieldName){
    return ((CXdbRecordset*)pObject)->GetFieldIndex(sFieldName);
}
bool CSRecordSet::IsMemoFileTable(void){
    return ((CXdbRecordset*)pObject)->IsMemoFileTable();
}
bool CSRecordSet::IsNumberField(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->IsNumberField(nFieldIndex);
}
bool CSRecordSet::GetFieldValueIntoBuffer(int nFieldIndex,char *pbuffer){
    return ((CXdbRecordset*)pObject)->GetFieldValueIntoBuffer(nFieldIndex,pbuffer);
}
void CSRecordSet::Edit(void){
    ((CXdbRecordset*)pObject)->Edit();
}
bool CSRecordSet::Update(void){
    return ((CXdbRecordset*)pObject)->Update();
}
bool CSRecordSet::SetFieldValue(int nFieldIndex, XdbVar& var){
    return ((CXdbRecordset*)pObject)->SetFieldValue(nFieldIndex,var);
}
bool CSRecordSet::SetFieldValueFromBuffer(int nFieldIndex,const char *pbuffer){
    return ((CXdbRecordset*)pObject)->SetFieldValueFromBuffer(nFieldIndex,pbuffer);
}
bool CSRecordSet::GetFieldValue(int nFieldIndex, XdbVar& var){
    return ((CXdbRecordset*)pObject)->GetFieldValue(nFieldIndex,var);
}
bool CSRecordSet::SeekRecord(XSEK *SEK){
    return ((CXdbRecordset*)pObject)->TableSeek(SEK);
}
bool CSRecordSet::SeekRecord(int nFieldIndex,char *key, int length){
    return ((CXdbRecordset*)pObject)->TableSeek(nFieldIndex,key,length);
}
bool CSRecordSet::SeekRecord(int nFieldIndex,long i){
    return ((CXdbRecordset*)pObject)->TableSeek(nFieldIndex,i);
}
bool CSRecordSet::SeekRecord(int nFieldIndex, double d, int decimals)
{
    return ((CXdbRecordset*)pObject)->TableSeek(nFieldIndex,d,decimals);
}
int CSRecordSet::GetRecordLength(void){
    return ((CXdbRecordset*)pObject)->GetRecordLength();
}
char *CSRecordSet::GetMemoField(int nMemoFieldIndex,char *pbuffer, int BUFFER_SIZE){
    return ((CXdbRecordset*)pObject)->GetMemoField(nMemoFieldIndex,pbuffer,BUFFER_SIZE);
}
bool CSRecordSet::GetBinaryField(unsigned char *buffer,long *buf_size){
    return ((CXdbRecordset*)pObject)->GetBinaryField(buffer,buf_size);
}
LPXSQL CSRecordSet::GetSQL(void){
    return ((CXdbRecordset*)pObject)->GetSQL();
}
void CSRecordSet::GoToLast(void){
    ((CXdbRecordset*)pObject)->GoToLast();
}
long CSRecordSet::GetRecordID(void){
    return ((CXdbRecordset*)pObject)->GetRecordID();
}
int CSRecordSet::GetStandardFieldCount(void){
    return ((CXdbRecordset*)pObject)->GetStandardFieldCount();
}
int CSRecordSet::GetTableType(void){
    return ((CXdbRecordset*)pObject)->GetTableType();
}
int CSRecordSet::GetFieldType(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->GetFieldType(nFieldIndex);
}
int CSRecordSet::GetFieldDGSize(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->GetFieldDGSize(nFieldIndex);
}
int CSRecordSet::GetFieldSize(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->GetFieldSize(nFieldIndex);
}

সম্পাদনা: ডেড এমএমজি দ্বারা অনুরোধ করা:

void nimportequoidumomentquecaroule(void) {

    short i = -4;
    unsigned short j=(unsigned short)i;

}

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

1
এতে কাস্ট করা DWORDআপত্তিজনক এবং সম্ভবত ভুল (DWORD একটি পয়েন্টার ধরে রাখার জন্য যথেষ্ট পরিমাণে প্রশস্ত নয়)। আপনার যদি একটি টাইপযুক্ত পয়েন্টার প্রয়োজন হয় void*তবে ব্যবহার করুন - তবে আপনি যখন নিজের প্রয়োজনটি সি ++ তে দেখেন, আপনি প্রায়শই আপনার কোডটিতে একটি ডিজাইনের সমস্যা পেয়েছিলেন যা আপনার ঠিক করা উচিত।
মাদুর

সালভাদোর, আমি মনে করি আপনি ভিসি 6 সম্পর্কে কিছু বলার চেষ্টা করছেন এবং এটি কীভাবে অস্বাভাবিক এবং অপ্রত্যাশিত পয়েন্টার পরিচালনা করছে। উদাহরণটি মন্তব্যে উপকৃত হতে পারে এবং আপনি যদি সংকলকটির কাছ থেকে সতর্কতা দেখছেন তবে তারা আপনার প্রশ্নের উত্তর সম্পর্কিত তথ্যমূলক হতে পারে।
বিকাশকারীরা

@ ম্যাট এই উদাহরণটি 32 বিট ওএস এবং ভিসি 6++ সংকলকের জন্য।
সালভাদোর

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