সুবিধাজনক সি ++ স্ট্রাক্টের সূচনা


141

আমি 'পড' সি ++ স্ট্রাক্টের সূচনা করার কোনও সুবিধাজনক উপায় সন্ধান করার চেষ্টা করছি। এখন, নিম্নলিখিত কাঠামো বিবেচনা করুন:

struct FooBar {
  int foo;
  float bar;
};
// just to make all examples work in C and C++:
typedef struct FooBar FooBar;

আমি যদি সি (!) এ সুবিধামত এটিকে সূচনা করতে চাই তবে আমি কেবল লিখতে পারি:

/* A */ FooBar fb = { .foo = 12, .bar = 3.4 }; // illegal C++, legal C

নোট করুন যে আমি নীচের স্বরলিপিটি স্পষ্টভাবে এড়াতে চাই, কারণ এটি যদি আমাকে ভবিষ্যতে কাঠামোর মধ্যে কিছু পরিবর্তন করে তবে আমার ঘাড়ে ভেঙে ফেলা হয়েছে বলে আমাকে আঘাত করে :

/* B */ FooBar fb = { 12, 3.4 }; // legal C++, legal C, bad style?

/* A */উদাহরণ হিসাবে সি ++ তে একই (বা কমপক্ষে অনুরূপ) অর্জন করতে , আমাকে একটি বোকামি নির্মাণকারী প্রয়োগ করতে হবে:

FooBar::FooBar(int foo, float bar) : foo(foo), bar(bar) {}
// ->
/* C */ FooBar fb(12, 3.4);

ফুটন্ত জলের জন্য কোনটি ভাল, তবে অলস লোকের পক্ষে উপযুক্ত নয় (অলসতা একটি ভাল জিনিস, তাই না?) এছাড়াও, /* B */উদাহরণের মতো এটি বেশ খারাপ , কারণ এটি স্পষ্টভাবে জানায় না কোন মানটি কোন সদস্যের কাছে যায়।

সুতরাং, আমার প্রশ্নটি মূলত আমি /* A */সি ++ এর অনুরূপ বা আরও ভাল কিছু কীভাবে অর্জন করতে পারি ? বিকল্পভাবে, আমি কেন এটি করতে চাইছি না (তার অর্থ কেন আমার মানসিক দৃষ্টান্তটি খারাপ) তার ব্যাখ্যা দিয়ে আমি ঠিক আছি।

সম্পাদনা

সুবিধামত দ্বারা , আমি মানে রক্ষণাবেক্ষণযোগ্য এবং অপ্রয়োজনীয়ও নয়


2
আমি মনে করি বি উদাহরণটি যতটা কাছাকাছি আপনি পেতে যাচ্ছেন।
মার্লন

2
বি কীভাবে "খারাপ স্টাইল" তা উদাহরণ দেখছি না। আপনি যেহেতু প্রতিটি সদস্যকে তাদের নিজ নিজ মানগুলির পরিবর্তে আরম্ভ করছেন তা এটি আমার কাছে বোধগম্য।
মাইক বেইলি

26
মাইক, এটি খারাপ স্টাইল কারণ কোন মানটি কোন সদস্যের কাছে যায় তা পরিষ্কার নয়। আপনাকে গিয়ে কাঠামোর সংজ্ঞাটি দেখতে হবে এবং তারপরে প্রতিটি মানটির অর্থ কী তা খুঁজে পেতে সদস্যদের গণনা করতে হবে।
jnnnnn

9
এছাড়াও, যদি ফুবার সংজ্ঞাটি ভবিষ্যতে পরিবর্তিত হয় তবে আরম্ভটি ভেঙে যেতে পারে।
এডওয়ার্ড ফালক

যদি সূচনাটি দীর্ঘ এবং জটিল হয়ে যায়, তবে বিল্ডার প্যাটার্নটি সম্পর্কে ভুলে যাবেন না
স্লেড করুন

উত্তর:


20

মনোনীত প্রারম্ভিকগুলি সি ++ 2 এ সমর্থিত হবে, তবে আপনাকে অপেক্ষা করতে হবে না, কারণ তারা আনুষ্ঠানিকভাবে জিসিসি, কলং এবং এমএসভিসি দ্বারা সমর্থিত

#include <iostream>
#include <filesystem>

struct hello_world {
    const char* hello;
    const char* world;
};

int main () 
{
    hello_world hw = {
        .hello = "hello, ",
        .world = "world!"
    };

    std::cout << hw.hello << hw.world << std::endl;
    return 0;
}

GCC Demo MSVC Demo


ক্যাভেট এমপোটার: মনে রাখবেন যে আপনি যদি পরে স্ট্রাক্টের শেষে পরামিতিগুলি যুক্ত করেন তবে পুরানো ইনিশিয়েশনগুলি এখনও আরম্ভ না করে নিঃশব্দে সংকলন করবে।
ক্যাটসকুল

1
@Catskul নং এটা সক্রিয়া করা হবে খালি সূচনাকারী তালিকা, যা শূন্য দিয়ে আরম্ভের মধ্যে হবে না।
ivaigult

তুমি ঠিক বলছো. ধন্যবাদ. আমার স্পষ্ট করা উচিত, বাকি পরামিতিগুলি নিঃশব্দে কার্যকরভাবে ডিফল্ট আরম্ভ হবে ized আমি যে বক্তব্যটি বোঝাতে চাইছিলাম তা হ'ল যে কেউ এই আশা করছেন তিনি পিওডি ধরণের সম্পূর্ণ সুস্পষ্ট সূচনা প্রয়োগে সহায়তা করতে পারেন হতাশ হবেন।
ক্যাটসকুল

43

যেহেতু style Aসি ++ এ অনুমোদিত নয় এবং আপনি style Bকীভাবে ব্যবহার করবেন তা চান না style BX:

FooBar fb = { /*.foo=*/ 12, /*.bar=*/ 3.4 };  // :)

কমপক্ষে কিছুটা হলেও সহায়তা করুন।


8
+1: এটি সত্যই সঠিক সূচনা নিশ্চিত করে না (সংকলক পিওভির কাছ থেকে) তবে পাঠককে নিশ্চিতভাবে সহায়তা করে ... যদিও মন্তব্যগুলি সমন্বয় করা উচিত।
ম্যাথিউ এম।

18
আমি যদি ভবিষ্যতে fooএবং এর barমধ্যে নতুন ক্ষেত্রটি সন্নিবেশ করি তবে মন্তব্য কাঠামোটির ভাঙা থেকে আরম্ভ হতে বাধা দেয় না । সি এখনও আমাদের ফিল্ডগুলি শুরু করতে পারে তবে সি ++ তা করবে না। এবং এটি প্রশ্নের বিন্দু - সি ++ তে একই ফলাফল কীভাবে অর্জন করবেন। আমার অর্থ, পাইথন নামযুক্ত যুক্তি দিয়ে এটি করে, সি - "নামযুক্ত" ক্ষেত্র সহ এবং সি ++ এরও কিছু হওয়া উচিত, আমি আশা করি।
দিমিত্রি_রোমানভ

2
সিঙ্কে মন্তব্য? আমাকে একটু বিরতি দাও. সুরক্ষা উইন্ডো দিয়ে যায়। প্যারামিটারগুলি এবং পুনরায় ক্রম করুন om সঙ্গে আরও ভাল explicit FooBar::FooBar(int foo, float bar) : foo(foo), bar(bar) সুস্পষ্ট কীওয়ার্ডটি নোট করুন । এমনকি মান ভঙ্গ করা সুরক্ষার ক্ষেত্রে আরও ভাল। ঝনঝনিতে: -নো-সি 99-এক্সটেনশনগুলি
ড্যানিয়েল ও

@ ড্যানিয়েলডাব্লু, এটি কী ভাল বা কোনটি নয় সে সম্পর্কে নয়। এই উত্তরটি অনুসারে যে ওপি স্টাইল এ (সি ++ নয়), বি বা সি চায় না, যা সমস্ত বৈধ কেসগুলিকে অন্তর্ভুক্ত করে।
iammilind

@ আইয়ামিলিন্ড আমি মনে করি কেন ওপির মানসিক দৃষ্টান্ত খারাপ কেন উত্তরটি আরও উন্নত করতে পারে h আমি এটি এখন যেমন বিপজ্জনক বিবেচনা করি।
ডায়ার্স্ট

10

আপনি একটি ল্যাম্বডা ব্যবহার করতে পারেন:

const FooBar fb = [&] {
    FooBar fb;
    fb.foo = 12;
    fb.bar = 3.4;
    return fb;
}();

এই অভিবাদন সম্পর্কিত আরও তথ্য হার্ব সটার ব্লগে পাওয়া যাবে ।


1
এই জাতীয় পদ্ধতির ক্ষেত্র দু'বার প্রারম্ভিক হয়। কনস্ট্রাক্টর একবার। দ্বিতীয়টি fb.XXX = YYY
Dmytro Ovdiienko

9

কনটেন্টগুলি ফাংশনগুলিতে নিষ্কাশন করুন যা সেগুলি বর্ণনা করে (বেসিক রিফ্যাক্টরিং):

FooBar fb = { foo(), bar() };

আমি জানি যে স্টাইলটি আপনি ব্যবহার করতে চান নি তার সাথে খুব কাছাকাছি, তবে এটি ধ্রুবক মানগুলির সহজ প্রতিস্থাপন সক্ষম করে এবং সেগুলি ব্যাখ্যা করে (এভাবে মন্তব্যগুলি সম্পাদনা করার প্রয়োজন হয় না), যদি তারা কখনও এটি পরিবর্তন করে।

আর একটি জিনিস যা আপনি করতে পেরেছিলেন (যেহেতু আপনি অলস) কনস্ট্রাক্টরকে ইনলাইন তৈরি করা হয়, তাই আপনাকে খুব বেশি টাইপ করতে হবে না ("ফুবার ::" অপসারণ এবং এইচ এবং সিপিপি ফাইলের মধ্যে স্যুইচিংয়ে ব্যয় করা সময়):

struct FooBar {
  FooBar(int f, float b) : foo(f), bar(b) {}
  int foo;
  float bar;
};

1
আমি এই উত্তরটি পড়ার জন্য যে কাউকে এই প্রশ্নের উত্তরটি পড়ার জন্য নীচের কোড-স্নিপেটে স্টাইলটি বেছে নেওয়ার জন্য উচ্চতর পরামর্শ দিচ্ছি যদি আপনি যা করতে চান তা যদি মানগুলির একটি সেট দিয়ে স্ট্রাক্টগুলি দ্রুত আরম্ভ করতে সক্ষম হয়।
kayleeFrye_onDeck

8

আপনার প্রশ্নটি কিছুটা জটিল কারণ এমনকি এটির কাজ:

static FooBar MakeFooBar(int foo, float bar);

হিসাবে বলা যেতে পারে:

FooBar fb = MakeFooBar(3.4, 5);

অন্তর্নির্মিত সংখ্যার প্রকারের জন্য প্রচার এবং রূপান্তর নিয়মের কারণে। (সি কখনও সত্যই দৃ strongly়ভাবে টাইপ করা হয়নি)

সি ++ এ, আপনি যা চান তা অর্জনযোগ্য, যদিও টেমপ্লেট এবং স্থিতিশীল দৃser়তার সাহায্যে:

template <typename Integer, typename Real>
FooBar MakeFooBar(Integer foo, Real bar) {
  static_assert(std::is_same<Integer, int>::value, "foo should be of type int");
  static_assert(std::is_same<Real, float>::value, "bar should be of type float");
  return { foo, bar };
}

সি তে, আপনি প্যারামিটারগুলির নাম দিতে পারেন, তবে আপনি আর কখনও পাবেন না।

অন্যদিকে, আপনার সমস্ত কিছু যদি প্যারামিটারের নামকরণ করা হয়, তবে আপনি প্রচুর পরিমাণে কোড লিখবেন:

struct FooBarMaker {
  FooBarMaker(int f): _f(f) {}
  FooBar Bar(float b) const { return FooBar(_f, b); }
  int _f;
};

static FooBarMaker Foo(int f) { return FooBarMaker(f); }

// Usage
FooBar fb = Foo(5).Bar(3.4);

এবং আপনি পছন্দ মতো মরিচ টাইপ প্রচার সুরক্ষা করতে পারেন।


1
"সি ++ এ, আপনি যা অর্জনযোগ্য তা": ওপি প্যারামিটারগুলির ক্রম মিশ্রণ প্রতিরোধে সহায়তা করতে বলছিল না? আপনার প্রস্তাবিত টেমপ্লেটটি কীভাবে এটি অর্জন করবে? কেবল সরলতার জন্য, আমাদের বলি যে আমাদের কাছে দুটি পরামিতি রয়েছে, উভয়ই অন্তর্নিহিত।
সর্বোচ্চ 23

@ ম্যাক্স: এটি কেবল তখনই প্রতিরোধ করবে যখন প্রকারভেদগুলি পৃথক হয় (এমনকি তারা একে অপরের সাথে রূপান্তরযোগ্য হলেও), এটি ওপি পরিস্থিতি। যদি এটি বিভিন্ন ধরণের পার্থক্য করতে না পারে তবে অবশ্যই এটি কাজ করে না, তবে এটি সম্পূর্ণ অন্য একটি প্রশ্ন।
ম্যাথিউ এম।

আহ পেয়েছে। হ্যাঁ, এটি দুটি পৃথক সমস্যা এবং আমার ধারণা, এই মুহুর্তে দ্বিতীয়টি সি ++ তে ভাল সমাধান পাবে না (তবে এটি সি ++ 20 সমষ্টিগত সূচনায় সি 99-স্টাইলের প্যারামিটার নামগুলির জন্য সমর্থন যোগ করছে)।
সর্বাধিক

6

অনেক সংকলকের সি ++ সম্মুখভাগ (জিসিসি এবং ঝনঝন সহ) সি ইনিশিয়াল সিনট্যাক্স বোঝে। আপনি যদি পারেন তবে কেবল সেই পদ্ধতিটি ব্যবহার করুন।


16
যা সি ++ স্ট্যান্ডার্ডের সাথে সঙ্গতিপূর্ণ নয়!
বিটমাস্ক

5
আমি জানি এটি মানহীন। তবে আপনি যদি এটি ব্যবহার করতে পারেন তবে এটি স্ট্রাক্ট শুরু করার সবচেয়ে বুদ্ধিমান উপায়।
ম্যাথিয়াস উরলিচস 21

2
আপনি ভুল কন্সট্রাক্টরকে প্রাইভেট বানানোর প্রকারের x এবং y রক্ষা করতে পারেন:private: FooBar(float x, int y) {};
দিমিত্রি_রোমানভ

4
ঝনঝন (llvm ভিত্তিক সি ++ সংকলক) এছাড়াও এই বাক্য গঠনটিকে সমর্থন করে। খুব খারাপ এটি মানক অংশ নয়।
নিমরোডম

আমরা সবাই জানি যে সি ইনিশিয়েলাইজাররা সি ++ স্ট্যান্ডার্ডের অংশ নয়। তবে অনেক সংকলক এটি বুঝতে পারে এবং কোন সংকলকটি কোন সংকলককে লক্ষ্যযুক্ত করা হচ্ছে তা প্রশ্নটি দেয় নি didn't সুতরাং দয়া করে এই উত্তরটি কমিয়ে দেবেন না।
ম্যাথিয়াস উরলিচস 13

4

তবুও সি ++ এর অন্য একটি উপায়

struct Point
{
private:

 int x;
 int y;

public:
    Point& setX(int xIn) { x = Xin; return *this;}
    Point& setY(int yIn) { y = Yin; return *this;}

}

Point pt;
pt.setX(20).setY(20);

2
ফাংশনাল প্রোগ্রামিংয়ের জন্য জটিল (যেমন কোনও ফাংশন কলের আর্গুমেন্ট তালিকায় অবজেক্ট তৈরি করা), তবে অন্যথায় সত্যিই একটি ঝরঝরে ধারণা!
বিটমাস্ক

27
অপ্টিমাইজার সম্ভবত এটি হ্রাস করে, তবে আমার চোখে পড়ে না।
ম্যাথিউ এম।

6
দুটি শব্দ: আরগ ... আরগ! পয়েন্ট পিটি দিয়ে জনসাধারণের ডেটা ব্যবহার করার চেয়ে এটি কীভাবে ভাল; pt.x = pt.y = 20; `? অথবা আপনি যদি এনক্যাপসুলেশন চান তবে এটি কনস্ট্রাক্টরের চেয়ে ভাল কীভাবে?
ওল্ডপেকুলিয়ার

3
এটি কনস্ট্রাক্টরের চেয়ে ভাল, কারণ আপনাকে প্যারামিটার অর্ডারের জন্য কনস্ট্রাক্টর ঘোষণার দিকে নজর দিতে হবে ... এটি কি এক্স, ওয়াই, ওয়াই, এক্স তবে আমি যেভাবে এটি দেখিয়েছি তা কল সাইটে স্পষ্টভাবে প্রমাণিত হয়েছে
পরপুরা রাজকুমার

2
আপনি যদি কনস্ট্রাক্ট স্ট্রাক্ট চান তবে এটি কাজ করে না। অথবা আপনি যদি সংকলকটি বলতে চান তা অনির্ধারিত স্ট্রাক্টের অনুমতি না দেয়। আপনি যদি সত্যিই এটি করতে চান তবে কমপক্ষে সেটারগুলি চিহ্নিত করুন inline!
ম্যাথিয়াস উরলিচস

3

বিকল্প ডি:

FooBar FooBarMake(int foo, float bar)

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

বিকল্প ই:

FooBar fb;
memset(&fb, 0, sizeof(FooBar));
fb.foo = 4;
fb.bar = 15.5f;

আইনী সি, আইনী সি ++। নাম যুক্তি।


12
মেমসেটের পরিবর্তে FooBar fb = {};আপনি সি ++ এ ব্যবহার করতে পারেন , এটি সমস্ত কাঠামোর সদস্যকে ডিফল্ট-সূচনা করে।
Öö তিবি

@ Iটাইব: দুর্ভাগ্যক্রমে এটি অবৈধ সি, যদিও।
সিবি বেইলি

3

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

#define INVALID_STRUCT_ERROR "Instantiation of struct failed: Type, order or number of attributes is wrong."

#define CREATE_STRUCT_1(type, identifier, m_1, p_1) \
{ p_1 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\

#define CREATE_STRUCT_2(type, identifier, m_1, p_1, m_2, p_2) \
{ p_1, p_2 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\

#define CREATE_STRUCT_3(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3) \
{ p_1, p_2, p_3 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\

#define CREATE_STRUCT_4(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3, m_4, p_4) \
{ p_1, p_2, p_3, p_4 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_4) >= (offsetof(type, m_3) + sizeof(identifier.m_3)), INVALID_STRUCT_ERROR);\

// Create more macros for structs with more attributes...

তারপরে আপনার কাছে কনস্ট বৈশিষ্ট্য সহ কোনও কাঠামো থাকে, আপনি এটি করতে পারেন:

struct MyStruct
{
    const int attr1;
    const float attr2;
    const double attr3;
};

const MyStruct test = CREATE_STRUCT_3(MyStruct, test, attr1, 1, attr2, 2.f, attr3, 3.);

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

তবে এটি আপনার সমস্যার সমাধান করে: আপনি যখন স্ট্রাক্টটি পরিবর্তন করেন, কলটি সংকলন-সময়ে ব্যর্থ হবে।

আপনি যদি সি ++ 17 ব্যবহার করেন তবে আপনি একই ধরণের জোর করে এই ম্যাক্রোগুলিকে আরও কঠোর করে তুলতে পারেন, যেমন:

#define CREATE_STRUCT_3(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3) \
{ p_1, p_2, p_3 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_1) == typeid(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_2) == typeid(identifier.m_2), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_3) == typeid(identifier.m_3), INVALID_STRUCT_ERROR);\

নামযুক্ত প্রারম্ভিকদের অনুমতি দেওয়ার জন্য কি কোনও সি ++ 20 প্রস্তাব রয়েছে?
মল নিসন


2

/* B */সি ++ তেও উপায় ভাল সি ++ 0x সিনট্যাক্সটি প্রসারিত করতে চলেছে তাই এটি সি ++ পাত্রেও কার্যকর। বুঝতে পারছি না কেন আপনি এটিকে খারাপ স্টাইল বলছেন?

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

স্ট্রাক্ট সদস্যদের পুনঃক্রম করা ফাংশন পরামিতিগুলির পুনঃক্রম করার মতো, আপনি যদি খুব যত্ন সহকারে এটি না করেন তবে এই ধরনের রিফ্যাক্টরিং সমস্যার কারণ হতে পারে।


7
আমি এটিকে খারাপ স্টাইল বলি কারণ আমি মনে করি এটি শূন্য রক্ষণাবেক্ষণযোগ্য। আমি যদি এক বছরে অন্য সদস্য যুক্ত করি? বা আমি যদি সদস্যদের অর্ডারিং / প্রকার পরিবর্তন করি? কোডের আরম্ভের প্রতিটি অংশ এটি (খুব সম্ভবত) বিরতিতে পারে।
বিটমাস্ক

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

2
যদি আপনি স্ট্রাক্টটি শেষ করতে এক বছরে অন্য সদস্য যুক্ত করেন তবে এটি ইতিমধ্যে বিদ্যমান কোডটিতে ডিফল্ট-আরম্ভ হবে। আপনি যদি এগুলি পুনরায় অর্ডার করেন তবে আপনাকে সমস্ত বিদ্যমান কোড সম্পাদনা করতে হবে, কিছুই করার নেই।
Öö তিবি

1
@ বিটমাস্ক: প্রথম উদাহরণটি তখন "অনিবার্য "ও হবে be আপনি যদি পরিবর্তে স্ট্রাক্টে কোনও ভেরিয়েবলের নাম পরিবর্তন করেন তবে কী হবে? অবশ্যই, আপনি একটি প্রতিস্থাপন সব করতে পারেন, তবে এটি ঘটনাক্রমে এমন একটি পরিবর্তনশীলটির নাম পরিবর্তন করতে পারে যা নাম পরিবর্তন করা উচিত নয়।
মাইক বেইলি

পছন্দ করেছেন সি গ্রুপ এবং সি 99 কোনও নির্দিষ্ট সংস্করণ / আইএসওর নির্দিষ্টকরণ নয়?
অ্যালেন্ডেকি

1

এই বাক্য গঠন সম্পর্কে কী?

typedef struct
{
    int a;
    short b;
}
ABCD;

ABCD abc = { abc.a = 5, abc.b = 7 };

সবেমাত্র একটি মাইক্রোসফ্ট ভিজ্যুয়াল সি ++ 2015 এবং জি ++ 6.0.2 এ পরীক্ষা করা হয়েছে। ঠিক আছে কাজ।
আপনি যদি ভেরিয়েবলের নাম সদৃশ করতে না চান তবে আপনি একটি নির্দিষ্ট ম্যাক্রোও তৈরি করতে পারেন।


clang++3.5.0-10 এর সাথে -Weverything -std=c++1zএটি নিশ্চিত হয়ে গেছে বলে মনে হচ্ছে। তবে এটি ঠিক দেখাচ্ছে না। আপনি কি জানেন যেখানে মানটি নিশ্চিত করে যে এটি বৈধ সি ++?
বিটমাস্ক

আমি জানি না, তবে আমি বহু কাল আগে থেকেই এটি বিভিন্ন সংকলকগুলিতে ব্যবহার করেছি এবং কোনও সমস্যা দেখিনি। এখন g ++ 4.4.7 এ পরীক্ষিত - ঠিক আছে।
ক্লাস

5
আমি এই কাজ মনে করি না। ব্যবহার করে দেখুন ABCD abc = { abc.b = 7, abc.a = 5 };
raymai97

@ নির্বাচিত, এটি কাজ করে কারণ ক্ষেত্রটি মান দিয়ে শুরু হয়, অপারেটর = দ্বারা ফিরে আসে। সুতরাং, আসলে আপনি ক্লাস মেম্বারকে দু'বার সূচনা করলেন।
Dmytro Ovdiienko

1

আমার জন্য ইনলাইন ইনিজায়ালাইজেশনের অনুমতি দেওয়ার সবচেয়ে অলস উপায়টি হল এই ম্যাক্রোটি।

#define METHOD_MEMBER(TYPE, NAME, CLASS) \
CLASS &set_ ## NAME(const TYPE &_val) { NAME = _val; return *this; } \
TYPE NAME;

struct foo {
    METHOD_MEMBER(string, attr1, foo)
    METHOD_MEMBER(int, attr2, foo)
    METHOD_MEMBER(double, attr3, foo)
};

// inline usage
foo test = foo().set_attr1("hi").set_attr2(22).set_attr3(3.14);

যে ম্যাক্রো বৈশিষ্ট্য এবং স্ব রেফারেন্স পদ্ধতি তৈরি করে।

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