সি ++ তে 'টাইপড' বনাম 'টাইপফ'


159

আমি ভাবছি সি ++ এর মধ্যে typeidএবং এর typeofমধ্যে পার্থক্য কী । আমি যা জানি তা এখানে:

  • typeidটাইপ_ইনফোর জন্য ডকুমেন্টেশনে উল্লেখ করা হয়েছে যা সি ++ হেডার ফাইল টাইপইনফোতে সংজ্ঞায়িত হয়েছে ।

  • typeofসি এর জন্য জিসিসি এক্সটেনশনে এবং সি ++ বুস্ট লাইব্রেরিতে সংজ্ঞায়িত করা হয় ।

এছাড়াও, এখানে আমি টেস্ট কোড পরীক্ষাটি তৈরি করেছি যা আমি তৈরি করেছি যেখানে আমি আবিষ্কার করেছি typeidযা আমার প্রত্যাশার সাথে ফিরে আসে না। কেন?

main.cpp

#include <iostream>  
#include <typeinfo>  //for 'typeid' to work  

class Person {  
    public:
    // ... Person members ...  
    virtual ~Person() {}  
};  

class Employee : public Person {  
    // ... Employee members ...  
};  

int main () {  
    Person person;  
    Employee employee;  
    Person *ptr = &employee;  
    int t = 3;  

    std::cout << typeid(t).name() << std::endl;  
    std::cout << typeid(person).name() << std::endl;   // Person (statically known at compile-time)  
    std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time)  
    std::cout << typeid(ptr).name() << std::endl;      // Person * (statically known at compile-time)  
    std::cout << typeid(*ptr).name() << std::endl;     // Employee (looked up dynamically at run-time  
                                                       // because it is the dereference of a pointer
                                                       // to a polymorphic class)  
 }  

আউটপুট:

bash-3.2$ g++ -Wall main.cpp -o main  
bash-3.2$ ./main   
i  
6Person  
8Employee  
P6Person  
8Employee

8
আপনি কীভাবে মনে করেন যে আপনার কোডটি সঠিক ধরণের নাম প্রিন্ট করে না? এটা আমার কাছে ভাল লাগছে. প্রকৃত স্ট্রিংটি name()বাস্তবায়ন-সংজ্ঞায়িত। এটি কোনও বৈধ সি ++ সনাক্তকারী নাম হতে হবে না, কেবল এমন কিছু যা টাইপটিকে স্বতন্ত্রভাবে সনাক্ত করে। দেখে মনে হচ্ছে আপনার বাস্তবায়নটি সংকলকের সাধারণ নাম-ম্যাংলিং স্কিমটি ব্যবহার করে।
রব কেনেডি

থ্যাঙ্কস রব! আমি এন.ইউইকিপিডিয়া.আর / উইকি / টাইপয়েডে যেমন দেখেছি ঠিক তেমন নামগুলির প্রত্যাশা করছিলাম। নাম-ম্যাংলিং এখানে কী করতে পারে?
টিম

আপনি যদি আমার মতো টাইপডে নতুন হন: ভিটিবেলটি চালু করতে আপনার বেস টাইপটিতে একটি ভার্চুয়াল ফাংশন প্রয়োজন বা শেষ লাইনটি বেস টাইপটি মুদ্রণ করবে।
jw_

উত্তর:


199

সি ++ ভাষার তেমন কোনও জিনিস নেই typeof। আপনার অবশ্যই কিছু সংকলক-নির্দিষ্ট এক্সটেনশনের দিকে তাকানো উচিত। আপনি যদি জিসিসির কথা বলছেন typeof, তবে কি-ওয়ার্ডের মাধ্যমে অনুরূপ বৈশিষ্ট্য সি ++ 11 এ উপস্থিত রয়েছে decltype। আবার, সি ++ এর মতো কোনও typeofকীওয়ার্ড নেই।

typeidএকটি সি ++ ভাষা অপারেটর যা রান সময়ে টাইপ সনাক্তকারী তথ্য দেয়। এটি মূলত একটি type_infoবস্তু ফেরত দেয় যা অন্যান্য type_infoবস্তুর সাথে সমতা-তুলনীয় ।

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

এটিও নোট করুন যে উপরেরটি সম্ভবত বোঝায় (যদিও মানটি এটি স্পষ্টভাবে উল্লেখ করেছে বলে মনে হচ্ছে না) typeidএকই ধরণের ক্রমাগত অ্যাপ্লিকেশনগুলি বিভিন্ন type_infoবস্তু ফিরে আসতে পারে (যা অবশ্যই সমান তুলনা করতে হবে)।


1
সি ++ 11 আছে যেহেতু এটির decltypeকি আপডেট দরকার ? আমি সাধারণ নীতিটি কী তা নিশ্চিত নই, তবে প্রশ্নটি ট্যাগ হওয়ার সাথে সাথে C++আমি এটি সর্বশেষ মানটি উল্লেখ করার প্রত্যাশা করব। যেমন প্রশ্ন Retagging C++03এছাড়াও একটি বিকল্প এই প্রোগ্রামটিতে হবে। আমি ব্যক্তিগতভাবে মাঝে মাঝে বেশ বিভ্রান্ত হয়ে পড়ে থাকি, কারণ আমাকে কাজের সময় প্রি ++ 11 ব্যবহার করতে হয় এবং কখনও কখনও আমি সত্য "প্রি 11" বা "পোস্ট 11" কী তা নিশ্চিত নই।
idclev 463035818

11
এফওয়াইআই, এর decltypeপ্রতিস্থাপন নয় typeoftypeofপ্রকারভেদেও কাজ করে যখন decltypeনা হয়। উদাহরণস্বরূপ, typeof(int)হয় intযখন decltype(int)একটি ত্রুটি।
শাহবাজ

1
" type_infoবিভিন্ন ধরণের বর্ণনা করা অবজেক্টগুলি অ-সমান তুলনা করবে" । আসলে, এটি গ্যারান্টিযুক্ত নয় । অসমতার অপারেটরটিকে সি ++ ২০ থেকে অপসারণ করা হয়েছে (আমি ধরে নিই) অ-সমান তুলনা করে বিভিন্ন ধরণের উপর নির্ভর করা নিরুৎসাহিত করে। তবে আপনি যদি এটির বিষয়ে চিন্তা করেন তবে বৈষম্য নিরাপদ না থাকলে সাম্যতা নিরাপদ নয়।
ইন্ডিয়ানা কার্নিক

51

উভয়ের মধ্যে প্রাথমিক পার্থক্যটি নিম্নরূপ

  • টাইপফ একটি সংকলন টাইম কনস্ট্রাক্ট এবং সংকলনের সময় সংজ্ঞায়িত অনুযায়ী টাইপটি প্রদান করে
  • টাইপড একটি রানটাইম কনস্ট্রাক্ট এবং তাই রানটাইম টাইপের মান সম্পর্কে তথ্য দেয়।

টাইপফুল রেফারেন্স: http://www.delorie.com/gnu/docs/gcc/gcc_36.html

টাইপড রেফারেন্স: https://en.wikedia.org/wiki/Typeid


ধন্যবাদ, জারেডপার! আপনার উত্তরগুলি পড়ার পরে আপডেট পোস্টে আমার কাছে কিছু নতুন প্রশ্ন রয়েছে। যেমন যদি এও সত্য যে তাদের রিটার্নগুলি বিভিন্ন উদ্দেশ্যে ব্যবহৃত হয়: টাইপফের রিটার্নটি টাইপ কীওয়ার্ড হিসাবে ব্যবহৃত হয় যা ভেরিয়েবলকে সংজ্ঞায়িত করতে পারে, তবে টাইপডের রিটার্ন কী পারে না?
টিম

26

typeidরানটাইম এ পরিচালনা করতে পারে এবং অবজেক্টের রান টাইম টাইপ বর্ণনা করে এমন একটি বস্তু ফিরিয়ে আনতে পারে যা ক্লাসে সংরক্ষণের জন্য আরটিটিআই (রান-টাইম টাইপ তথ্য) করার জন্য ভার্চুয়াল পদ্ধতি সহ কোনও শ্রেণীর কোনও পয়েন্টার হতে হবে। এটি রান-টাইম ধরণের তথ্য সহ কোনও শ্রেণিকে কোনও পয়েন্টার না দিলে সংক্ষেপে টাইপ টাইপের একটি এক্সপ্রেশন বা একটি টাইপের নামও দিতে পারে।

typeofএটি একটি জিএনইউ এক্সটেনশন এবং সংকলনের সময় আপনাকে যে কোনও এক্সপ্রেশনের ধরণ দেয়। উদাহরণস্বরূপ, একাধিক ধরণের ক্ষেত্রে ব্যবহৃত হতে পারে এমন ম্যাক্রোগুলিতে অস্থায়ী পরিবর্তনশীলগুলি ঘোষণার ক্ষেত্রে এটি দরকারী হতে পারে। সি ++ এ আপনি সাধারণত পরিবর্তে টেম্পলেট ব্যবহার করবেন।


5
আমি যতদূর জানি, typeidযে কোনও অভিব্যক্তি গ্রহণ করবে, কেবল ভার্চুয়াল পদ্ধতিগুলির সাথে অবজেক্টগুলির মূল্যায়ন করে না। তদুপরি, কোনও অভিব্যক্তি নয়, typeidকোনও প্রকারের নাম গ্রহণ করবে । বলতে পারেন typeid(5)বা typeid(std::string)চাইলে বলতে পারেন।
রব কেনেডি

1
আমি আমার উত্তরটি পরিষ্কার করে দিয়েছি; typeid করতে রান-টাইম রিটার্ন টাইপ তথ্য যদি পাওয়া যায়, কিন্তু অন্য কিছু জন্য কম্পাইল সময় টাইপ তথ্য প্রদান করবে।
ব্রায়ান ক্যাম্পবেল

আপনাকে ধন্যবাদ, ব্রায়ান এবং রব! আপনার উত্তরগুলি পড়ার পরে আপডেট পোস্টে আমার কাছে কিছু নতুন প্রশ্ন রয়েছে।
টিম

22

অতিরিক্ত প্রশ্নের উত্তর:

টাইপডের জন্য আমার নিম্নলিখিত পরীক্ষার কোডটি সঠিক ধরণের নাম আউটপুট দেয় না। কোনো সমস্যা?

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


এগুলি দুটি ভিন্ন সরঞ্জাম। typeofএকটি এক্সপ্রেশনের ধরণটি প্রদান করে তবে এটি মানক নয়। সি ++ 0 এক্সে এমন কিছু বলা আছে decltypeযা একই কাজ আফাইক করে।

decltype(0xdeedbeef) number = 0; // number is of type int!
decltype(someArray[0]) element = someArray[0];

যেখানে typeidপলিমারফিক ধরণের ব্যবহার করা হয়। উদাহরণস্বরূপ, এটি বলতে দিনcat আহরিত animal:

animal* a = new cat; // animal has to have at least one virtual function
...
if( typeid(*a) == typeid(cat) )
{
    // the object is of type cat! but the pointer is base pointer.
}

ধন্যবাদ, আরাক! আমি কিছু নতুন প্রশ্ন সহ পোস্টটি আপডেট করেছি। সম্ভব হলে দয়া করে একবার দেখুন।
টিম

4

টাইপড যখন জিজ্ঞাসা করা হয় তখন রানটাইমের সময় ডেটার প্রকার সরবরাহ করে। টাইপডিফ একটি সংকলন সময় গঠন যা তার পরে বর্ণিত হিসাবে একটি নতুন টাইপ সংজ্ঞায়িত করে। সি ++ আউটপুটে কোনও টাইপফুল উপস্থিত নেই (শিলালিপিযুক্ত মন্তব্য হিসাবে দেখানো হয়েছে):

std::cout << typeid(t).name() << std::endl;  // i
std::cout << typeid(person).name() << std::endl;   // 6Person
std::cout << typeid(employee).name() << std::endl; // 8Employee
std::cout << typeid(ptr).name() << std::endl;      // P6Person
std::cout << typeid(*ptr).name() << std::endl;     //8Employee

3

আপনি দেখতে সুন্দর একটি নাম অর্জন করতে বুস্ট ডেম্যাঙ্গেল ব্যবহার করতে পারেন:

#include <boost/units/detail/utility.hpp>

এবং কিছু

To_main_msg_evt ev("Failed to initialize cards in " + boost::units::detail::demangle(typeid(*_IO_card.get()).name()) + ".\n", true, this);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.