সি ++ তে 'স্ট্রাক্ট' এবং 'টাইপডিফ স্ট্রাক্ট' এর মধ্যে পার্থক্য?


834

ইন সি ++ , সেখানে মধ্যে কোনো পার্থক্য নেই:

struct Foo { ... };

এবং:

typedef struct { ... } Foo;


উত্তর:


1200

সি ++ এ কেবল একটি সূক্ষ্ম পার্থক্য রয়েছে। এটি সি থেকে একটি হোল্ডওভার, এতে এটি একটি পার্থক্য করে।

সি ভাষার মান ( C89 893.1.2.3 , C99 §6.2.3 , এবং C11 .26.2.3 ) ট্যাগ শনাক্তকারীদের ( struct/ union/ enum) এবং সাধারণ সনাক্তকারীদের ( typedefএবং অন্যান্য শনাক্তকারীদের জন্য ) সহ বিভিন্ন বিভাগের শনাক্তকারীদের জন্য পৃথক নেমস্পেসগুলি নির্দেশ করে ates

আপনি যদি কেবল বলেছেন:

struct Foo { ... };
Foo x;

আপনি একটি সংকলক ত্রুটি পাবেন, কারণ Fooশুধুমাত্র ট্যাগ নেমস্পেসে সংজ্ঞায়িত।

আপনি এটি হিসাবে ঘোষণা করতে চাই:

struct Foo x;

আপনি যে কোনও সময় রেফারেন্স করতে চান Foo, আপনাকে সর্বদা এটিকে ডাকতে হবে struct Foo। এটি বিরক্তিকর দ্রুত হয়, যাতে আপনি একটি যুক্ত করতে পারেন typedef:

struct Foo { ... };
typedef struct Foo Foo;

এখন struct Foo(ট্যাগ নেমস্পেসে) এবং কেবল প্লেইন Foo(সাধারণ শনাক্তকারী নেমস্পেসে) উভয়ই একই জিনিসটিকে বোঝায় এবং আপনি কীওয়ার্ড Fooছাড়াই নির্বিঘ্নে টাইপের অবজেক্টগুলি ঘোষণা করতে পারেন struct


নির্মাণ:

typedef struct Foo { ... } Foo;

ঘোষণার জন্য কেবল একটি সংক্ষেপণ এবং typedef


অবশেষে,

typedef struct { ... } Foo;

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


সি ++ এ, সমস্ত struct/ union/ enum/ classঘোষণাগুলি এগুলি স্পষ্টতই typedef'এড' এর মতো কাজ করে , যতক্ষণ না একই নামের সাথে অন্য কোনও ঘোষণার মাধ্যমে নামটি গোপন করা হয় না। দেখুন মাইকেল চোরকাঁটা এর উত্তর সম্পূর্ণ বিবরণের জন্য।


53
আপনি যা বলছেন তা সত্য, আফাইক, বিবৃতি, 'টাইপেডেফ স্ট্রাক্ট {...} ফু;' নামবিহীন কাঠামোর জন্য একটি উপাধি তৈরি করে।
dirkgently

25
ভাল ধরা, "টাইপেফ স্ট্রাক্ট ফু between ...} ফু;" এর মধ্যে একটি সূক্ষ্ম পার্থক্য রয়েছে; এবং "টাইপেডেফ স্ট্রাক্ট {...} ফু;"।
অ্যাডাম রোজনফিল্ড 21

8
সি তে, স্ট্রাক্ট ট্যাগগুলি, ইউনিয়ন ট্যাগগুলি এবং গণনা ট্যাগগুলি উপরের দাবি অনুসারে দুটি ব্যবহার করে (স্ট্রাক্ট এবং ইউনিয়ন) না করে একটি নামস্পেস ভাগ করে; টাইপিডেফ নামের জন্য উল্লিখিত নাম স্থানটি পৃথক পৃথক। তার মানে আপনার দুটি ইউনিয়ন থাকতে পারে না x ...}; ' এবং 'স্ট্রাক্ট x {...};' একক সুযোগে।
জোনাথন লেফলার

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

1
@Lazer আছে: হয় সূক্ষ্ম পার্থক্য, কিন্তু আদম উপায়ে (তিনি বলে যায়) আপনি একটি typedef ছাড়া ভেরিয়েবল ডিক্লেয়ার 'প্রকার Var' ব্যবহার করতে পারেন।
ফ্রেড নুরক

226

ইন এই DDJ নিবন্ধ , ড্যান Saks এক ছোটো এলাকার যেখানে বাগ মাধ্যমে হামাগুড়ি পারেন যদি আপনি আপনার structs মধ্যে হয় typedef না ব্যাখ্যা (এবং ক্লাস!):

আপনি যদি চান তবে আপনি কল্পনা করতে পারেন যে সি ++ প্রতিটি ট্যাগ নামের জন্য টাইপডেফ তৈরি করে

typedef class string string;

দুর্ভাগ্যক্রমে, এটি সম্পূর্ণ সঠিক নয়। আমি আশা করি এটি সহজ ছিল, কিন্তু এটি না। সি ++ সি এর সাথে অসঙ্গতিগুলি প্রবর্তন না করে স্ট্রাক্ট, ইউনিয়ন বা এনামগুলির জন্য এ জাতীয় টাইপডেফ তৈরি করতে পারে না

উদাহরণস্বরূপ, ধরুন একটি সি প্রোগ্রাম কোনও ফাংশন এবং স্ট্রাক্ট নামের স্থিতি উভয়ই ঘোষণা করেছে:

int status(); struct status;

আবার এটি খারাপ অভ্যাস হতে পারে তবে এটি সি। এই প্রোগ্রামে স্ট্যাটাস (নিজে থেকেই) ফাংশনকে বোঝায়; কাঠামোর অবস্থা প্রকারকে বোঝায়।

যদি সি ++ ট্যাগগুলির জন্য স্বয়ংক্রিয়ভাবে টাইপডেফ তৈরি করে, তবে আপনি যখন এই প্রোগ্রামটি সি ++ হিসাবে সংকলন করবেন তখন সংকলকটি উত্পন্ন করবে:

typedef struct status status;

দুর্ভাগ্যক্রমে, এই ধরণের নামটি ফাংশন নামের সাথে বিরোধ করবে এবং প্রোগ্রামটি সংকলন করবে না। এজন্য সি ++ প্রতিটি ট্যাগের জন্য কেবল টাইপডেফ তৈরি করতে পারে না।

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

সুতরাং, একটি সি প্রোগ্রাম যাতে উভয় থাকে:

int status(); struct status;

সি ++ হিসাবে সংকলিত হওয়ার সময় একই আচরণ করে। নাম স্থিতি একা ফাংশন বোঝায়। প্রোগ্রামটি কেবল বর্ণিত-টাইপ-স্পেসিফায়ার স্ট্রাক স্থিতি ব্যবহার করে প্রকারটি উল্লেখ করতে পারে।

তাহলে কীভাবে এটি বাগগুলিকে প্রোগ্রামগুলিতে ডুবে যেতে দেয়? তালিকা 1 এ প্রোগ্রামটি বিবেচনা করুন । এই প্রোগ্রামটি একটি ডিফল্ট কন্সট্রাক্টর এবং একটি রূপান্তরকারী অপারেটর সহ একটি ক্লাস ফু সংজ্ঞায়িত করে যা কোনও foo অবজেক্টটিকে চর কনস্ট * রূপান্তর করে। এখনও বিক্রয়ের জন্য

p = foo();

মূলত একটি foo অবজেক্ট তৈরি করা উচিত এবং রূপান্তর অপারেটর প্রয়োগ করা উচিত। পরবর্তী আউটপুট বিবৃতি

cout << p << '\n';

ক্লাস foo প্রদর্শন করা উচিত, কিন্তু এটি না। এটি ফাংশন ফু প্রদর্শন করে।

এই আশ্চর্যজনক ফলাফলটি ঘটে কারণ প্রোগ্রামটি 2 টি তালিকায় প্রদর্শিত শিরোনাম lib.h অন্তর্ভুক্ত করে । এই শিরোনাম foo নামে একটি ফাংশন সংজ্ঞায়িত করে। ফাংশন নেম foo ক্লাসের নাম foo গোপন করে, সুতরাং foo- র মূল উল্লেখটি ফাংশনকে বোঝায়, শ্রেণি নয়। মেইন কেবলমাত্র একটি বিস্তৃত-টাইপ-স্পেসিফায়ার ব্যবহার করে ক্লাসটি উল্লেখ করতে পারে

p = class foo();

পুরো প্রোগ্রাম জুড়ে এই জাতীয় বিভ্রান্তি এড়ানোর উপায়টি ক্লাস নাম foo এর জন্য নিম্নলিখিত টাইপডেফ যুক্ত করা:

typedef class foo foo;

ক্লাস সংজ্ঞা আগে বা পরে অবিলম্বে। এই টাইপডিফ প্রকারের নাম foo এবং ফাংশন নাম foo (লাইব্রেরি থেকে) এর মধ্যে দ্বন্দ্ব সৃষ্টি করে যা একটি সংকলন-সময় ত্রুটি ট্রিগার করবে।

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

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


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

Listing 1এবং Listing 2লিঙ্কগুলি নষ্ট হয়ে গেছে। একবার দেখুন।
প্রসূন সৌরভ

3
আপনি যদি ক্লাস এবং ফাংশনগুলির জন্য বিভিন্ন নামকরণের কনভেনশন ব্যবহার করেন তবে অতিরিক্ত টাইপডেফ যোগ করার প্রয়োজন ছাড়াই আপনি নামকরণের বিরোধও এড়াতে পারবেন।
zstewart

64

আরও একটি গুরুত্বপূর্ণ পার্থক্য: typedefগুলি এগিয়ে ঘোষণা করা যায় না। তাই জন্য typedefবিকল্পটি আবশ্যক #includeফাইল ধারণকারী typedef, সবকিছু অর্থ #includeকরা আপনার .hকাছে যে ফাইল তা সরাসরি দরকার বা না, ইত্যাদি অন্তর্ভুক্ত করা হয়েছে। এটি অবশ্যই বড় প্রকল্পগুলিতে আপনার বিল্ড বারকে প্রভাবিত করতে পারে।

ছাড়া typedef, কিছু কিছু ক্ষেত্রে আপনি শুধু একটা ফরওয়ার্ড ঘোষণা যোগ করতে পারেন struct Foo;আপনার উপরের .hফাইল, এবং শুধুমাত্র #includeআপনার struct সংজ্ঞা .cppফাইল।


কাঠামোর সংজ্ঞাটি প্রকাশের কারণে বিল্ড সময়কে প্রভাবিত করে কেন? যখন সংস্থাপকটি Foo * NextFoo এর মতো কিছু দেখেন তখন (টাইপিডেফ বিকল্পটি দেওয়া হয়, যাতে সংকলক সংজ্ঞাটি জানতে পারে) এমনকি কী কী অতিরিক্ত চেকিংও করে; ?
ধনী

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

দয়া করে @ পূর্ববর্তী মন্তব্যকারী (পোস্টের মালিক ব্যতীত)। আমি আপনার উত্তরটি প্রায় মিস করেছি। কিন্তু তথ্যটির জন্য ধন্যবাদ।
সমৃদ্ধ

এটি সি 11 এ আর সত্য নয়, যেখানে আপনি একই নামের সাথে একই কাঠামোটি বেশ কয়েকবার টাইপ করতে পারেন।
মাইকেলমায়ার

32

সেখানে হয় একটি পার্থক্য, কিন্তু সূক্ষ্ম। এটি এইভাবে দেখুন: struct Fooএকটি নতুন টাইপ প্রবর্তন। দ্বিতীয়টি একটি নামবিহীন structপ্রকারের জন্য ফু (এবং কোনও নতুন ধরণের নয়) নামে একটি উপনাম তৈরি করে ।

7.1.3 টাইপডেফ নির্দিষ্টকরণকারী specif

1 [...]

টাইপডেফ স্পেসিফায়ারের সাথে ঘোষিত একটি নাম টাইপএফ-নাম হয়ে যায়। এর ঘোষণার ক্ষেত্রের মধ্যে, একটি টাইপিডেফ-নামটি মূলত একটি কীওয়ার্ডের সমতুল্য এবং ক্লোজ ৮-এ বর্ণিত পদ্ধতিতে সনাক্তকারীর সাথে সম্পর্কিত ধরণের নামকরণ করে A টাইপডেফ-নামটি অন্যভাবে একটি প্রতিশব্দ। ক্লাস ঘোষণাপত্র (9.1) বা এনাম ডিকোলেমেশন যেভাবে টাইপইফ -নাম একটি নতুন ধরণের প্রবর্তন করে না

8 যদি টাইপডেফ ঘোষণাপত্র একটি নামবিহীন শ্রেণি (বা এনাম) সংজ্ঞায়িত করে তবে ঘোষণাপত্রের দ্বারা ঘোষিত প্রথম টাইপডিফ-নামটি শ্রেণীর প্রকার (বা এনাম টাইপ) হিসাবে সংযোগের উদ্দেশ্যে কেবল শ্রেণিবদ্ধ (বা এনাম টাইপ) বোঝাতে ব্যবহৃত হয় ( 3.5)। [উদাহরণ:

typedef struct { } *ps, S; // S is the class name for linkage purposes

সুতরাং, একটি টাইপিডেফ সর্বদা অন্য ধরণের স্থানধারক / প্রতিশব্দ হিসাবে ব্যবহৃত হয়।


10

আপনি টাইপডেফ স্ট্রাক্টের সাথে ফরোয়ার্ড ঘোষণাটি ব্যবহার করতে পারবেন না।

কাঠামো নিজেই একটি বেনামি ধরণের, সুতরাং আপনার কাছে ফরওয়ার্ড দেওয়ার জন্য প্রকৃত নাম নেই।

typedef struct{
    int one;
    int two;
}myStruct;

এই অদম্য কাজের মতো একটি অগ্রণী ঘোষণা:

struct myStruct; //forward declaration fails

void blah(myStruct* pStruct);

//error C2371: 'myStruct' : redefinition; different basic types

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

@ রিচ এটি অভিযোগ করছে যে নামের বিরোধ রয়েছে। "মাইস্ট্রাক্ট নামক স্ট্রাক্টের সন্ধান করুন" বলে একটি ফরোয়ার্ড ঘোষণা রয়েছে এবং তারপরে টাইপডেফ রয়েছে যা একটি নামহীন কাঠামোটির নামকরণ করে "মাই স্ট্রাক্ট"।
ইয়োচাই টিমমার

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

: @Rich জিসিসি একই ভুল দেয়, পাঠ্য একটু পরিবর্তিত হয় gcc.godbolt.org/...
Yochai Timmer

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

0

সি ++ তে একটি 'টাইপডিফ স্ট্রাক্ট' এবং 'স্ট্রাক্ট' এর মধ্যে একটি গুরুত্বপূর্ণ পার্থক্য হ'ল টাইপডেফ স্ট্রাইকগুলিতে ইনলাইন সদস্য সূচনাটি কাজ করবে না।

// the 'x' in this struct will NOT be initialised to zero
typedef struct { int x = 0; } Foo;

// the 'x' in this struct WILL be initialised to zero
struct Foo { int x = 0; };

3
সত্য না. উভয় ক্ষেত্রেই xসূচনা করা হয়। কলিরু অনলাইন আইডিইতে পরীক্ষা দেখুন (আমি এটিকে 42 দিয়ে শুরু করেছিলাম তাই কাজটি শূন্যের চেয়ে আরও বেশি স্পষ্ট যে অ্যাসাইনমেন্টটি সত্যই ঘটেছে)।
কলিন ডি বেনেট

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

-3

সি ++ তে কোনও পার্থক্য নেই, তবে আমি সিতে বিশ্বাস করি এটি আপনাকে স্পষ্টভাবে না করে স্ট্রাক্ট ফু এর উদাহরণগুলি ঘোষণা করার অনুমতি দেবে:

struct Foo bar;

3
@ Dirkgently এর উত্তর এ লুক --- সেখানে হয় একটি পার্থক্য, কিন্তু এটা সূক্ষ্ম।
কিথ পিনসন

-3

স্ট্রাক্ট একটি ডেটা টাইপ তৈরি করা হয়। টাইপডিফ একটি ডেটা টাইপের জন্য একটি ডাক নাম সেট করতে হয়।


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