কোনও ঘোষণা কী স্ট্যান্ড নেমস্পেসকে প্রভাবিত করতে পারে?


96
#include <iostream>
#include <cmath>

/* Intentionally incorrect abs() which seems to override std::abs() */
int abs(int a) {
    return a > 0? -a : a;
}

int main() {
    int a = abs(-5);
    int b = std::abs(-5);
    std::cout<< a << std::endl << b << std::endl;
    return 0;
}

আমি আশা করেছিলাম যে আউটপুটটি হবে -5এবং 5তবে আউটপুটটি হ'ল -5এবং -5

আমি ভাবছি কেন এই মামলা হবে?

এর ব্যবহার stdবা কিছু ব্যবহারের সাথে কি কিছু আছে ?


4
আপনার বাস্তবায়ন absভুল।
রিচার্ড ক্রিটেন

31
@ রিচার্ড ক্রিটটেন এই বিষয়টি। ওপি এর জিজ্ঞেস কেন ভাঙ্গা যোগ করার absপ্রভাবিত std::abs()
হলিব্ল্যাকগেট

11
আকর্ষণীয়, আমি পেতে 5এবং 5ঝনঝন সঙ্গে, -5এবং -5সিসি সঙ্গে।
Rakete1111

10
Cmake একটি সংকলক নয়, বরং একটি বিল্ড সিস্টেম। আপনি বিভিন্ন সংকলক দিয়ে তৈরি করতে cmake ব্যবহার করতে পারেন।
হলিব্ল্যাকগেট

5
আমি সম্ভবত আপনাকে কেবল আপনার ফাংশনটি দেওয়ার প্রস্তাব দিই return 0- এটি লোকেরা আপনাকে অনিচ্ছাকৃতভাবে ফাংশনটি ভুলভাবে কার্যকর করে এবং পছন্দসই এবং প্রকৃত আচরণকে আরও পরিষ্কার করে দেওয়া এড়াতে পারে।
বার্নহার্ড বার্কার

উত্তর:


92

ভাষা স্পেসিফিকেশন পারবেন বাস্তবায়নের বাস্তবায়ন <cmath>প্রকাশক (এবং সংজ্ঞা) এ মান ফাংশন দ্বারা বিশ্বব্যাপী নামস্থান এবং তারপর তাদের নামস্থান মধ্যে আনয়ন stdব্যবহার-ঘোষণা মাধ্যমে। এই পদ্ধতির ব্যবহার হয়েছে কিনা তা অনির্দিষ্ট

20.5.1.2 শিরোলেখ
4 [...] সি ++ স্ট্যান্ডার্ড লাইব্রেরিতে, তবে, ঘোষণাগুলি (সিতে ম্যাক্রো হিসাবে সংজ্ঞায়িত নামগুলি বাদে) নামের স্থানটির নাম স্থানের (6.3.6) মধ্যে রয়েছে std। এই নামগুলি (ক্লজ 21 মাধ্যমে 33 এবং আনেক্স ডি-তে যোগ হওয়া কোনও ওভারলোড সহ) প্রথমে বিশ্বব্যাপী নেমস্পেসের স্কোপের মধ্যে ঘোষণা করা হয়েছে এবং তারপরে stdসুস্পষ্টভাবে ব্যবহারের মাধ্যমে ঘোষণার মাধ্যমে (10.3.3) নেমস্পেসে ইনজেকশন দেওয়া আছে কিনা তা অনির্দিষ্ট ified

স্পষ্টতই, আপনি যে কোনও বাস্তবায়নের সাথে মোকাবিলা করছেন যা এই পদ্ধতির অনুসরণ করার সিদ্ধান্ত নিয়েছে (যেমন জিসিসি)। যেমন আপনার বাস্তবায়ন সরবরাহ করে ::abs, যখন std::absকেবল "রেফারেন্স" দেয় ::abs

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

এই দুটি কারণ একসাথে আপনি যে প্রভাবটি লক্ষ্য করেন তা তৈরি করে: দুর্বল-প্রতীক প্রতিস্থাপনের ফলে প্রতিস্থাপনের ::absফলস্বরূপ std::abs। ভাষার মানের সাথে এটি কতটা ভালভাবে একমত হয় তা অন্যরকম গল্প ... কোনও অবস্থাতেই, এই আচরণের উপর নির্ভর করবেন না - এটি ভাষা দ্বারা গ্যারান্টিযুক্ত নয়।

জিসিসিতে এই আচরণটি নিম্নোক্ত উদাহরণ সহকারে পুনরুত্পাদন করা যেতে পারে। একটি উত্স ফাইল

#include <iostream>

void foo() __attribute__((weak));
void foo() { std::cout << "Hello!" << std::endl; }

অন্য উত্স ফাইল

#include <iostream>

void foo();
namespace N { using ::foo; }

void foo() { std::cout << "Goodbye!" << std::endl; }

int main()
{
  foo();
  N::foo();
}

এই ক্ষেত্রে আপনি আরও লক্ষ্য করবেন যে দ্বিতীয় উত্স ফাইলে ::foo( "Goodbye!") এর নতুন সংজ্ঞাটি এর আচরণকেও প্রভাবিত করে N::foo। উভয় কল আউটপুট হবে "Goodbye!"। এবং যদি আপনি ::fooদ্বিতীয় উত্স ফাইল থেকে সংজ্ঞাটি সরিয়ে থাকেন তবে উভয় কলই "মূল" সংজ্ঞা ::fooএবং আউটপুট প্রেরণ করবে "Hello!"


উপরের 20.5.1.2/4 দ্বারা প্রদত্ত অনুমতিটি এর বাস্তবায়ন সহজ করার জন্য রয়েছে <cmath>। বাস্তবায়নগুলিকে কেবল সি-স্টাইল অন্তর্ভুক্ত করার অনুমতি দেওয়া হয় <math.h>, তারপরে ক্রিয়াকলাপগুলিকে পুনরায় ঘোষিত করতে stdএবং কিছু সি ++ যুক্ত করুন - নির্দিষ্ট সংযোজন এবং টুইটগুলি। যদি উপরের ব্যাখ্যাটি সমস্যার অভ্যন্তরীণ যান্ত্রিকভাবে সঠিকভাবে বর্ণনা করে, তবে এর একটি বড় অংশটি কার্যকারিতাগুলির সি-স্টাইল সংস্করণের দুর্বল চিহ্নগুলির প্রতিস্থাপনের উপর নির্ভর করে ।

মনে রাখবেন যদি কেবলমাত্র আমরা বিশ্বব্যাপী প্রতিস্থাপন intসঙ্গে doubleউপরে প্রোগ্রামে, কোড (জিসিসি অধীনে) "হিসাবে প্রত্যাশিত" আচরণ করবে - এটা আউটপুট হবে -5 5। সি স্ট্যান্ডার্ড লাইব্রেরির abs(double)কার্যকারিতা না থাকার কারণে এটি ঘটে । আমাদের নিজস্ব ঘোষণা দিয়ে abs(double), আমরা কিছু প্রতিস্থাপন করি না।

কিন্তু যদি থেকে স্যুইচ করার পরে intসঙ্গে doubleআমরা থেকে সুইচ absকরতে fabs, মূল অদ্ভুত আচরণ তার পূর্ণ গরিমা (আউটপুটে পুনরায় প্রদর্শিত হবে -5 -5)।

এটি উপরোক্ত ব্যাখ্যার সাথে সামঞ্জস্যপূর্ণ।


যেহেতু আমি cmath উত্সে দেখতে পাচ্ছি তাই এর using ::abs;মত কোনও মত নেই using ::asin;তাই আপনি এই ঘোষণাকে ওভাররাইড করতে পারেন, উল্লেখ করার মতো অন্য একটি বিষয় হ'ল স্ট্যান্ডার্ড নেমস্পেস ফাংশনগুলিতে সংজ্ঞায়িত ইন্টের জন্য ঘোষণা করা হয়নি বরং এটির জন্য
হ'ল স্টাড সংখ্যার

4
স্ট্যান্ডার্ডের দৃষ্টিকোণ থেকে, আচরণটি [extern.names] / 4 অনুযায়ী অপরিবর্তিত
এক্সস্কক্সজার

তবে আমি যখন #include<cmath>আমার কোডটিতে ডিলিট করেছিলাম তখন একই উত্তর পেয়েছি got
পিটার

@ পিটার তবে আপনি কোথা থেকে স্টাড :: অ্যাবস পেয়ে যাচ্ছেন? - এটি অন্য অন্তর্ভুক্তের মাধ্যমে অন্তর্ভুক্ত করা হতে পারে, আপনি এই ব্যাখ্যাটিতে ফিরে এসেছেন। (কোনও শিরোনাম প্রত্যক্ষ বা অপ্রত্যক্ষভাবে অন্তর্ভুক্ত করা থাকলে সংকলকটির কোনও ব্যাপার নয়))
আরএম

@ পিটার: এছাড়াও absঘোষণা করা <cstdlib>যেতে পারে, যা স্পষ্টভাবে এর মাধ্যমে অন্তর্ভুক্ত করা যেতে পারে <iostream>। আপনার নিজেরটি অপসারণ absএবং এটি এখনও সংকলন করে কিনা দেখুন।
এএনটি

13

আপনার কোড অনির্ধারিত আচরণের কারণ।

সি ++ 17 [বাহ্যিক নাম]] / 4:

বহিরাগত সংযোগের সাথে ঘোষিত সি স্ট্যান্ডার্ড লাইব্রেরি থেকে প্রতিটি ফাংশন স্বাক্ষর বহিরাগত "সি" এবং বহিরাগত "সি ++" লিঙ্কেজ সহ ফাংশন স্বাক্ষর হিসাবে বা বিশ্বব্যাপী নেমস্পেসের নাম স্থানের নাম হিসাবে ব্যবহারের জন্য বাস্তবায়নের জন্য সংরক্ষিত the

সুতরাং আপনি স্ট্যান্ডার্ড সি লাইব্রেরি ফাংশনের মতো একই প্রোটোটাইপ দিয়ে কোনও ফাংশন তৈরি করতে পারবেন না int abs(int);। আপনি আসলে কোন শিরোলেখকে অন্তর্ভুক্ত করছেন বা সেই শিরোনামগুলি সি লাইব্রেরির নামগুলি বিশ্বব্যাপী নেমস্পেসে রাখে তা নির্বিশেষে।

তবে absআপনি যদি বিভিন্ন পরামিতি প্রকার সরবরাহ করেন তবে এটি ওভারলোডের অনুমতি দেওয়া হবে ।


4
"বা বিশ্বব্যাপী নেমস্পেসে নেমস্পেসের স্কোপের একটি নাম হিসাবে", তাই এটি বিশ্বব্যাপী নেমস্পেসে ওভারলোড করা যায় না।
xskxzr

@xskxzr আপনার উদ্ধৃত পাঠ্যের ব্যাখ্যার বিষয়ে আমি নিশ্চিত নই; যদি এটির অর্থ গ্রহণ করা হয় যে ব্যবহারকারী বিশ্বব্যাপী নেমস্পেসে name নামের কোনও কিছুই প্রকাশ করতে না পারে তবে আমি উদ্ধৃত পাঠ্যের পূর্ববর্তী অংশটি রিডান্টান হবে, বেশিরভাগ [extern.names] / 3। যা আমাকে ভাবতে পরিচালিত করে যে এখানে অন্য কিছু উদ্দেশ্য ছিল।
এমএম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.