- කුමක්ද කරන්නේ වස්තුවක් පිටපත් අදහස්?
- මොකක්ද? පිටපතක් ඉදිකිරීමටත් හා පිටපතක් පැවරුම ක්රියාකරු ?
- ඒවා මා විසින්ම ප්රකාශ කිරීමට අවශ්ය වන්නේ කවදාද?
- මගේ වස්තූන් පිටපත් කිරීම වළක්වා ගන්නේ කෙසේද?
Answers:
C ++ පරිශීලක අර්ථ දක්වන ලද වර්ගවල විචල්යයන් අගය අර්ථ නිරූපණයන් සමඟ සලකයි . මෙයින් අදහස් කරන්නේ වස්තූන් විවිධ සන්දර්භයන් තුළ ව්යංගයෙන් පිටපත් කර ඇති අතර “වස්තුවක් පිටපත් කිරීම” යන්නෙන් සැබවින්ම අදහස් කරන්නේ කුමක්ද යන්න අප තේරුම් ගත යුතුය.
අපි සරල උදාහරණයක් සලකා බලමු:
class person
{
std::string name;
int age;
public:
person(const std::string& name, int age) : name(name), age(age)
{
}
};
int main()
{
person a("Bjarne Stroustrup", 60);
person b(a); // What happens here?
b = a; // And here?
}
(ඔබ name(name), age(age)
කොටසින් ව්යාකූල වී ඇත්නම් , මෙය සාමාජික ආරම්භක ලැයිස්තුවක් ලෙස හැඳින්වේ .)
person
වස්තුවක් පිටපත් කිරීම යන්නෙන් අදහස් කරන්නේ කුමක්ද? මෙම main
කාර්යය පැහැදිලි පිටපත් සිදුවීම් දෙකක් පෙන්වයි. ආරම්භ person b(a);
කිරීම පිටපත් සාදන්නා විසින් සිදු කරනු ලැබේ . එහි කාර්යය වන්නේ පවතින වස්තුවක තත්වය මත පදනම්ව නැවුම් වස්තුවක් තැනීමයි. පැවරුම පිටපත් පැවරුම් ක්රියාකරුb = a
විසින් සිදු කරනු ලැබේ . එහි කාර්යය සාමාන්යයෙන් මඳක් සංකීර්ණ වේ, මන්ද ඉලක්කගත වස්තුව දැනටමත් යම් වලංගු තත්වයක පවතින බැවින් එය සමඟ කටයුතු කළ යුතුය.
පිටපත් සාදන්නා හෝ පැවරුම් ක්රියාකරු (හෝ විනාශ කරන්නා) අප විසින්ම ප්රකාශයට පත් කර නොමැති හෙයින්, මේවා අපට ව්යංගයෙන් අර්ථ දක්වා ඇත. සම්මතයෙන් උපුටා ගැනීම:
[...] පිටපත් සාදන්නා සහ පිටපත් පැවරුම් ක්රියාකරු, [...] සහ විනාශ කරන්නා විශේෂ සාමාජික කාර්යයන් වේ. [ සටහන : වැඩසටහන පැහැදිලිව ප්රකාශ නොකරන විට සමහර පන්ති වර්ග සඳහා මෙම සාමාජික ක්රියාකාරකම් ක්රියාත්මක කිරීම ව්යංගයෙන් ප්රකාශ කරනු ඇත. ඒවා භාවිතා කරන්නේ නම් ක්රියාත්මක කිරීම මඟින් ඒවා ව්යංගයෙන් අර්ථ දක්වනු ඇත. [...] අවසන් සටහන ] [n3126.pdf 12 වන කොටස]
පෙරනිමියෙන්, වස්තුවක් පිටපත් කිරීම යනු එහි සාමාජිකයන් පිටපත් කිරීම ය:
යූනියන් නොවන පංතිය සඳහා ව්යංගයෙන් නිර්වචනය කරන ලද පිටපත් සාදන්නා එහි උප විෂයයන්හි සාමාජික පිටපතක් සිදු කරයි. [n3126.pdf කොටස 12.8 §16]
X නොවන පන්තිය සඳහා ව්යංගයෙන් නිර්වචනය කරන ලද පිටපත් පැවරුම් ක්රියාකරු එහි උප විෂයයන්හි සාමාජික පිටපත් කිරීමේ පැවරුම සිදු කරයි. [n3126.pdf කොටස 12.8 §30]
මේ සඳහා person
පෙනුම සඳහා ව්යංගයෙන් අර්ථ දක්වා ඇති විශේෂ සාමාජික කාර්යයන් :
// 1. copy constructor
person(const person& that) : name(that.name), age(that.age)
{
}
// 2. copy assignment operator
person& operator=(const person& that)
{
name = that.name;
age = that.age;
return *this;
}
// 3. destructor
~person()
{
}
Memberwise පිටපත් අපි මේ අවස්ථාවේ දී අවශ්ය දේ හරියටම:
name
හා age
අපි ස්වයං අන්තර්ගත ස්වාධීන ලබා නිසා, පිටපත් person
වස්තුව. ව්යංගයෙන් නිර්වචනය කරන ලද විනාශ කරන්නා සෑම විටම හිස් ය. ඉදිකිරීම්කරුගේ සම්පත් අප විසින් අත්පත් කර නොගත් බැවින් මෙයද මෙම අවස්ථාවේ දී හොඳයි. සාමාජිකයාගේ විනාශ කරන්නන් ව්යංගයෙන් කැඳවනු person
ලැබේ.
විනාශ කරන්නාගේ ශරීරය ක්රියාත්මක කිරීමෙන් සහ ශරීරය තුළ වෙන් කර ඇති ඕනෑම ස්වයංක්රීය වස්තුවක් විනාශ කිරීමෙන් පසුව, X පන්තියේ විනාශ කරන්නෙකු X හි සෘජු [...] සාමාජිකයන් සඳහා විනාශ කරන්නන් අමතයි [n3126.pdf 12.4 §6]
ඉතින් අපි එම විශේෂ සාමාජික ක්රියාකාරකම් පැහැදිලිව ප්රකාශ කළ යුත්තේ කවදාද? අපේ පන්තිය සම්පතක් කළමනාකරණය කරන විට, එනම් පන්තියේ වස්තුවක් එම සම්පත සඳහා වගකිව යුතු විට. සාමාන්යයෙන් එයින් අදහස් වන්නේ සම්පත ඉදිකිරීම්කරු තුළ අත්පත් කර ගැනීම (හෝ ඉදිකිරීම්කරු වෙත ලබා දීම) සහ විනාශ කරන්නා තුළ මුදා හැරීමයි.
පූර්ව සම්මත C ++ වෙත අපි නැවත යමු. එබඳු දෙයක් නොතිබූ අතර std::string
, ක්රමලේඛකයින් දර්ශකයන්ට ආදරය කළහ. මෙම person
පන්ති මේ හා සමාන ය ඇති විය:
class person
{
char* name;
int age;
public:
// the constructor acquires a resource:
// in this case, dynamic memory obtained via new[]
person(const char* the_name, int the_age)
{
name = new char[strlen(the_name) + 1];
strcpy(name, the_name);
age = the_age;
}
// the destructor must release this resource via delete[]
~person()
{
delete[] name;
}
};
අදටත් මිනිසුන් මෙම ශෛලිය තුල පන්ති ලියන අතර කරදරයට පත්වේ: " මම පුද්ගලයෙකු දෛශිකයකට තල්ලු කළෙමි, දැන් මට පිස්සු මතක දෝෂ ඇතිවේ ! " පෙරනිමියෙන්, වස්තුවක් පිටපත් කිරීම යනු එහි සාමාජිකයන් පිටපත් කිරීම name
පමණක් නොව සාමාජිකයා පිටපත් කිරීම පමණක් බව මතක තබා ගන්න. පිටපත් අවධානය යොමුකළ, නෑ එය පෙන්නුම් චරිතය අරා! මෙය අප්රසන්න බලපෑම් කිහිපයක් ඇත:
a
නිරීක්ෂණය කළ හැකිය b
.b
විනාශ වූ පසු , a.name
අන්තරාදායක දර්ශකයකි.a
විනාශ වුවහොත් , අන්තරාදායක දර්ශකය මකා දැමීමෙන් නිර්වචනය නොකළ හැසිරීමක් ලැබේ.name
පෙර පෙන්වා දුන් දේ සැලකිල්ලට නොගන්නා හෙයින් , ඉක්මනින් හෝ පසුව ඔබට සෑම තැනකම මතක කාන්දු වේ.සාමාජික වශයෙන් පිටපත් කිරීම අපේක්ෂිත බලපෑමක් නොමැති බැවින්, අක්ෂර අරාවේ ගැඹුරු පිටපත් සෑදීම සඳහා අපි පිටපත් සාදන්නා සහ පිටපත් පැවරුම් ක්රියාකරු පැහැදිලිව අර්ථ දැක්විය යුතුය:
// 1. copy constructor
person(const person& that)
{
name = new char[strlen(that.name) + 1];
strcpy(name, that.name);
age = that.age;
}
// 2. copy assignment operator
person& operator=(const person& that)
{
if (this != &that)
{
delete[] name;
// This is a dangerous point in the flow of execution!
// We have temporarily invalidated the class invariants,
// and the next statement might throw an exception,
// leaving the object in an invalid state :(
name = new char[strlen(that.name) + 1];
strcpy(name, that.name);
age = that.age;
}
return *this;
}
ආරම්භ කිරීම සහ පැවරුම අතර වෙනස සැලකිල්ලට ගන්න: name
මතක කාන්දු වීම වැළැක්වීම සඳහා පැවරීමට පෙර අපි පැරණි තත්වය ඉරා දැමිය යුතුය . එසේම, පෝරමයේ ස්වයං පැවරුමෙන් ආරක්ෂා විය යුතුය x = x
. එම පරීක්ෂාවකින් තොරව, ප්රභවdelete[] name
නූල අඩංගු අරාව මකා දමනු ඇත , මන්ද ඔබ ලියන විට දෙකම සහ එකම දර්ශකය අඩංගු වේ.x = x
this->name
that.name
අවාසනාවකට මෙන්, new char[...]
මතක වෙහෙස නිසා ව්යතිරේකයක් විසි කළහොත් මෙම විසඳුම අසාර්ථක වනු ඇත . හැකි එක් විසඳුමක් නම් දේශීය විචල්යයක් හඳුන්වා දීම සහ ප්රකාශ නැවත සකස් කිරීම:
// 2. copy assignment operator
person& operator=(const person& that)
{
char* local_name = new char[strlen(that.name) + 1];
// If the above statement throws,
// the object is still in the same state as before.
// None of the following statements will throw an exception :)
strcpy(local_name, that.name);
delete[] name;
name = local_name;
age = that.age;
return *this;
}
මෙය පැහැදිලි පරීක්ෂාවකින් තොරව ස්වයං පැවරුම ගැන සැලකිලිමත් වේ. මෙම ගැටළුවට ඊටත් වඩා ශක්තිමත් විසඳුමක් වන්නේ පිටපත් හා හුවමාරු මෝඩකමයි , නමුත් මම මෙහි ව්යතිරේක ආරක්ෂාව පිළිබඳ විස්තර වෙත නොයමි. පහත සඳහන් කරුණ ඉදිරිපත් කිරීම සඳහා මම ව්යතිරේක පමණක් සඳහන් කළෙමි: සම්පත් කළමනාකරණය කරන පන්ති ලිවීම දුෂ්කර ය.
සමහර සම්පත් ගොනු හැසිරවීම් හෝ මූටෙක්ස් වැනි පිටපත් කළ නොහැක. එවැනි අවස්ථාවක, private
අර්ථ දැක්වීමක් ලබා නොදී පිටපත් සාදන්නා සහ පිටපත් පැවරුම් ක්රියාකරු ලෙස ප්රකාශ කරන්න :
private:
person(const person& that);
person& operator=(const person& that);
විකල්පයක් ලෙස, ඔබට boost::noncopyable
ඒවා මකාදැමූ බව උරුම කර ගැනීමට හෝ ප්රකාශ කිරීමට හැකිය (C ++ 11 සහ ඊට ඉහළින්):
person(const person& that) = delete;
person& operator=(const person& that) = delete;
සමහර විට ඔබ සම්පතක් කළමනාකරණය කරන පන්තියක් ක්රියාත්මක කිරීමට අවශ්ය වේ. (තනි පන්තියක කිසි විටෙකත් බහු සම්පත් කළමනාකරණය නොකරන්න, මෙය වේදනාවට පමණක් හේතු වේ.) එවැනි අවස්ථාවකදී, තුනේ රීතිය මතක තබා ගන්න :
ඔබට විනාශ කරන්නා, පිටපත් සාදන්නා හෝ පිටපත් පැවරුම් ක්රියාකරු පැහැදිලිව ප්රකාශ කිරීමට අවශ්ය නම්, ඔබ ඔවුන් තිදෙනාම පැහැදිලිව ප්රකාශ කළ යුතුය.
(අවාසනාවකට මෙන්, මෙම "රීතිය" සී ++ ප්රමිතිය හෝ මා දන්නා කිසිදු සම්පාදකයෙකු විසින් බලාත්මක නොකෙරේ.)
C ++ 11 සිට, වස්තුවකට අමතර විශේෂ සාමාජික කාර්යයන් 2 ක් ඇත: චලන ඉදිකිරීම්කරු සහ චලනය පැවරීම. මෙම කාර්යයන් ක්රියාත්මක කිරීම සඳහා ප්රාන්ත පහක රීතිය.
අත්සන් සහිත උදාහරණයක්:
class person
{
std::string name;
int age;
public:
person(const std::string& name, int age); // Ctor
person(const person &) = default; // Copy Ctor
person(person &&) noexcept = default; // Move Ctor
person& operator=(const person &) = default; // Copy Assignment
person& operator=(person &&) noexcept = default; // Move Assignment
~person() noexcept = default; // Dtor
};
3/5 හි නියමය 0/3/5 හි රීතිය ලෙස ද හැඳින්වේ. රීතියේ ශුන්ය කොටසෙහි දැක්වෙන්නේ ඔබේ පන්තිය නිර්මාණය කිරීමේදී විශේෂ සාමාජික කාර්යයන් කිසිවක් ලිවීමට ඔබට අවසර නැති බවයි.
බොහෝ විට, ඔබ විසින්ම සම්පතක් කළමනාකරණය කර ගැනීමට අවශ්ය නොවේ, මන්ද දැනටමත් පවතින පන්තියක් std::string
ඔබ වෙනුවෙන් එය කරයි. std::string
සාමාජිකයෙකු භාවිතා කර සරල කේතයක් සංසන්දනය කර දෝෂ සහිත විකල්පයක් සමඟ සංසන්දනය කරන්න . char*
එවිට ඔබට ඒත්තු ගැන්විය යුතුය. ඔබ අමු දර්ශක සාමාජිකයන්ගෙන් stay ත්ව සිටින තාක් කල්, තුන්දෙනෙකුගේ රීතිය ඔබේ කේතය ගැන සැලකිලිමත් වීමට අපහසුය.
මෙම ත්රී ආධිපත්යය, මූලික වශයෙන් කියමින්, C ++ සඳහා විශේෂයෙන් සැලකිලිමත් නීතියක් වේ
ඔබේ පන්තියට කිසිවක් අවශ්ය නම්
- එය පිටපත් ඉදිකිරීමටත් ,
- ක පැවරුම ක්රියාකරු ,
- හෝ විනාශ කරන්නෙකු ,
පැහැදිලිව අර්ථ දක්වා ඇති විට, ඒ තුනම අවශ්ය වනු ඇත .
මේ සඳහා හේතු වන්නේ ඔවුන් තිදෙනාම සාමාන්යයෙන් සම්පතක් කළමනාකරණය කිරීම සඳහා භාවිතා කරන අතර ඔබේ පන්තිය සම්පතක් කළමනාකරණය කරන්නේ නම්, සාමාන්යයෙන් පිටපත් කිරීම මෙන්ම නිදහස් කිරීමද කළමනාකරණය කළ යුතුය.
ඔබේ පන්තිය කළමනාකරණය කරන සම්පත පිටපත් කිරීම සඳහා හොඳ අර්ථකථනයක් නොමැති නම් , පිටපත් සාදන්නා සහ පැවරුම් ක්රියාකරු ලෙස ප්රකාශ කිරීමෙන් ( නිර්වචනය නොකොට ) පිටපත් කිරීම තහනම් කිරීමට සලකා බලන්න private
.
. තුන්වන නියමය ගැන.)
boost::noncopyable
) පන්තියකින් (පුද්ගලිකව) උරුම වීමයි. එය වඩාත් පැහැදිලි විය හැකිය. C ++ 0x සහ කාර්යයන් "මකාදැමීමේ" හැකියාව මෙහි උපකාරී වනු ඇතැයි මම සිතමි, නමුත් වාක්ය
noncopyable
කොටසක් නොවේ නම්, එය වැඩි දියුණුවක් ලෙස මම නොසිතමි. (ඔහ්, ඔබට මකාදැමීමේ වාක්ය :)
විශාල තිදෙනාගේ නීතිය ඉහත දක්වා ඇති පරිදි වේ.
සරල ඉංග්රීසියෙන්, එය විසඳන ආකාරයේ ගැටලුවකට පහසු උදාහරණයක්:
පෙරනිමි නොවන විනාශ කරන්නා
ඔබ ඔබේ ඉදිකිරීම්කරු තුළ මතකය වෙන් කර ඇති අතර එය මකා දැමීමට ඔබට ඩිස්ට්රැක්ටරයක් ලිවිය යුතුය. එසේ නොමැතිනම් ඔබ මතක කාන්දුවක් ඇති කරයි.
මෙය කාර්යයක් යැයි ඔබ සිතනු ඇත.
ගැටළුව වනුයේ, පිටපතක් ඔබේ වස්තුවෙන් සාදා ඇත්නම්, පිටපත මුල් වස්තුවට සමාන මතකයක් වෙත යොමු කරනු ඇත.
වරක්, මේවායින් එකක් එහි විනාශකයේ ඇති මතකය මකා දැමූ විට, අනෙකාට අවලංගු මතකය සඳහා දර්ශකයක් ඇත (මෙය ඩන්ග්ලිං පොයින්ටරයක් ලෙස හැඳින්වේ) එය භාවිතා කිරීමට උත්සාහ කරන විට දේවල් කෙස් ගසනු ඇත.
එමනිසා, ඔබ පිටපත් සාදන්නෙකු ලියන අතර එමඟින් නව වස්තූන් විනාශ කිරීමට ඔවුන්ගේ මතක කොටස් වෙන් කරයි.
පැවරුම් ක්රියාකරු සහ පිටපත් සාදන්නා
ඔබේ පන්තියේ සාමාජික දර්ශකය වෙත ඔබේ ඉදිකිරීම්කරු තුළ මතකය වෙන් කර ඇත. ඔබ මෙම පන්තියේ වස්තුවක් පිටපත් කරන විට පෙරනිමි පැවරුම් ක්රියාකරු සහ පිටපත් සාදන්නා විසින් මෙම සාමාජික දර්ශකයේ වටිනාකම නව වස්තුවට පිටපත් කරනු ඇත.
මෙයින් අදහස් කරන්නේ නව වස්තුව සහ පැරණි වස්තුව එකම මතක කොටසකට යොමු වන බැවින් ඔබ එය එක් වස්තුවක වෙනස් කරන විට අනෙක් වස්තුව සඳහා ද එය වෙනස් වන බවයි. එක් වස්තුවක් මෙම මතකය මකා දැමුවහොත් අනෙකා එය භාවිතා කිරීමට උත්සාහ කරයි - eek.
මෙය විසඳීම සඳහා ඔබ පිටපත් සාදන්නාගේ සහ පැවරුම් ක්රියාකරුගේ ඔබේම පිටපතක් ලියයි. ඔබගේ අනුවාදයන් නව වස්තූන් සඳහා වෙනම මතකයක් වෙන් කර පළමු දර්ශකය යොමු කරන අගයන් හරහා එහි ලිපිනයට වඩා පිටපත් කරන්න.
මූලික වශයෙන් ඔබ සතුව ඩිස්ට්රැක්ටරයක් තිබේ නම් (පෙරනිමි ඩිස්ට්රැක්ටර් නොවේ) එයින් අදහස් කරන්නේ ඔබ නිර්වචනය කළ පන්තියට යම් මතක වෙන් කිරීමක් ඇති බවයි. පන්තිය පිටත භාවිතා කරන්නේ යම් සේවාදායක කේතයක් හෝ ඔබ විසින් යැයි සිතමු.
MyClass x(a, b);
MyClass y(c, d);
x = y; // This is a shallow copy if assignment operator is not provided
මයික්ලාස් හි ඇත්තේ ප්රාථමික ටයිප් කළ සාමාජිකයන් කිහිප දෙනෙකු පමණක් නම් පෙරනිමි පැවරුම් ක්රියාකරුවෙකු ක්රියා කරනු ඇත, නමුත් එහි සමහර දර්ශක සාමාජිකයන් සහ පැවරුම් ක්රියාකරුවන් නොමැති වස්තූන් තිබේ නම් ප්රති result ලය අනාවැකි කිව නොහැකි වනු ඇත. එබැවින් අපට කිව හැක්කේ පංතියක විනාශ කරන්නා තුළ මකා දැමීමට යමක් තිබේ නම්, අපට ගැඹුරු පිටපත් ක්රියාකරුවෙකු අවශ්ය විය හැකි අතර එයින් අදහස් කරන්නේ අපි පිටපත් සාදන්නෙකු සහ පැවරුම් ක්රියාකරුවෙකු සැපයිය යුතු බවයි.
වස්තුවක් පිටපත් කිරීමෙන් අදහස් කරන්නේ කුමක්ද? ඔබට වස්තු පිටපත් කළ හැකි ක්රම කිහිපයක් තිබේ - ඔබ බොහෝ විට සඳහන් කරන වර්ග 2 ගැන කතා කරමු - ගැඹුරු පිටපත සහ නොගැඹුරු පිටපත.
අප සිටින්නේ වස්තු-නැඹුරු භාෂාවක බැවින් (හෝ අවම වශයෙන් එසේ උපකල්පනය කරයි), අපි ඔබට මතක කොටසක් වෙන් කර ඇති බව කියමු. එය OO- භාෂාවක් බැවින්, අප විසින් වෙන් කරන ලද මතක කොටස් පහසුවෙන් යොමු කළ හැකිය, මන්ද ඒවා සාමාන්යයෙන් ප්රාථමික විචල්යයන් (ints, chars, bytes) හෝ අප විසින් නිර්වචනය කරන ලද පන්ති අපගේම වර්ග හා ප්රාථමික වලින් සාදා ඇත. එබැවින් අපි පහත පරිදි කාර් වර්ගයක් ඇති බව කියමු:
class Car //A very simple class just to demonstrate what these definitions mean.
//It's pseudocode C++/Javaish, I assume strings do not need to be allocated.
{
private String sPrintColor;
private String sModel;
private String sMake;
public changePaint(String newColor)
{
this.sPrintColor = newColor;
}
public Car(String model, String make, String color) //Constructor
{
this.sPrintColor = color;
this.sModel = model;
this.sMake = make;
}
public ~Car() //Destructor
{
//Because we did not create any custom types, we aren't adding more code.
//Anytime your object goes out of scope / program collects garbage / etc. this guy gets called + all other related destructors.
//Since we did not use anything but strings, we have nothing additional to handle.
//The assumption is being made that the 3 strings will be handled by string's destructor and that it is being called automatically--if this were not the case you would need to do it here.
}
public Car(const Car &other) // Copy Constructor
{
this.sPrintColor = other.sPrintColor;
this.sModel = other.sModel;
this.sMake = other.sMake;
}
public Car &operator =(const Car &other) // Assignment Operator
{
if(this != &other)
{
this.sPrintColor = other.sPrintColor;
this.sModel = other.sModel;
this.sMake = other.sMake;
}
return *this;
}
}
ගැඹුරු පිටපතක් යනු අප වස්තුවක් ප්රකාශයට පත් කර පසුව සම්පූර්ණයෙන්ම වෙනම පිටපතක් නිර්මාණය කරන්නේ නම් ... අපි අවසන් වන්නේ වස්තු 2 ක් සමඟ සම්පූර්ණයෙන්ම මතක කට්ටල 2 කිනි.
Car car1 = new Car("mustang", "ford", "red");
Car car2 = car1; //Call the copy constructor
car2.changePaint("green");
//car2 is now green but car1 is still red.
දැන් අපි අමුතු දෙයක් කරමු. කාර් 2 සෑදී ඇත්තේ වැරදි ලෙස හෝ හිතාමතාම කාර් 1 සෑදී ඇති සැබෑ මතකය බෙදා ගැනීමට යැයි කියමු. . වේ.
//Shallow copy example
//Assume we're in C++ because it's standard behavior is to shallow copy objects if you do not have a constructor written for an operation.
//Now let's assume I do not have any code for the assignment or copy operations like I do above...with those now gone, C++ will use the default.
Car car1 = new Car("ford", "mustang", "red");
Car car2 = car1;
car2.changePaint("green");//car1 is also now green
delete car2;/*I get rid of my car which is also really your car...I told C++ to resolve
the address of where car2 exists and delete the memory...which is also
the memory associated with your car.*/
car1.changePaint("red");/*program will likely crash because this area is
no longer allocated to the program.*/
එබැවින් ඔබ ලියන භාෂාව කුමක් වුවත්, වස්තූන් පිටපත් කිරීමේදී ඔබ අදහස් කරන්නේ කුමක්ද යන්න පිළිබඳව ඉතා සැලකිලිමත් වන්න, මන්ද බොහෝ විට ඔබට ගැඹුරු පිටපතක් අවශ්ය වේ.
පිටපත් සාදන්නා සහ පිටපත් පැවරුම් ක්රියාකරු යනු කුමක්ද? මම දැනටමත් ඒවා ඉහත භාවිතා කර ඇත. ඔබ Car car2 = car1;
අත්යාවශ්යයෙන්ම කේතයක් ටයිප් කරන විට පිටපත් සාදන්නා ලෙස හැඳින්වෙන්නේ ඔබ විචල්යයක් ප්රකාශ කර එය එක් පේළියකට පවරන්නේ නම්, එවිට පිටපත් සාදන්නා ලෙස හැඳින්වේ. පැවරුම් ක්රියාකරු යනු ඔබ සමාන ලකුණක් භාවිතා කරන විට සිදු වන දෙයයි car2 = car1;
. car2
එකම ප්රකාශයේ දැන්වීම ප්රකාශයට පත් නොකෙරේ. මෙම මෙහෙයුම් සඳහා ඔබ ලියන කේත කැබලි දෙක බොහෝ දුරට සමාන ය. ආරම්භක පිටපත / පැවරුම නීත්යානුකූල බව ඔබ සෑහීමකට පත්වූ පසු සෑම දෙයක්ම සැකසීමට සාමාන්ය මෝස්තර රටාවට තවත් කාර්යයක් ඇත - මා ලියා ඇති දිගු කේතය දෙස බැලුවහොත්, කාර්යයන් බොහෝ දුරට සමාන වේ.
ඒවා මා විසින්ම ප්රකාශ කිරීමට අවශ්ය වන්නේ කවදාද? ඔබ බෙදාහදා ගැනීමට හෝ යම් ආකාරයකින් නිෂ්පාදනය කිරීමට කේතයක් ලියන්නේ නැත්නම්, ඔබට ඒවා ප්රකාශ කිරීමට අවශ්ය වන්නේ ඔබට අවශ්ය විටදී පමණි. ඔබ එය 'අහම්බෙන්' භාවිතා කිරීමට තෝරාගෙන එකක් සෑදුවේ නැත්නම් ඔබේ වැඩසටහන් භාෂාව කරන්නේ කුමක්ද යන්න පිළිබඳව ඔබ දැනුවත් විය යුතුය - එනම් ඔබට සම්පාදක පෙරනිමිය ලැබේ. උදාහරණයක් ලෙස මම පිටපත් සාදන්නන් භාවිතා කරන්නේ කලාතුරකිනි, නමුත් පැවරුම් ක්රියාකරු අභිබවා යාම ඉතා සුලභ ය. එකතු කිරීම, අඩු කිරීම යනාදියෙහි තේරුම ද ඉක්මවා යා හැකි බව ඔබ දැන සිටියාද?
මගේ වස්තූන් පිටපත් කිරීම වළක්වා ගන්නේ කෙසේද? පුද්ගලික ශ්රිතයක් සමඟ ඔබේ වස්තුව සඳහා මතකය වෙන් කිරීමට ඔබට අවසර දී ඇති සියලු ක්රම ඉක්මවා යන්න සාධාරණ ආරම්භයකි. මිනිසුන් ඒවා පිටපත් කිරීම ඔබට ඇත්තටම අවශ්ය නැතිනම්, ඔබට එය ප්රසිද්ධ කළ හැකි අතර ව්යතිරේකයක් විසි කිරීමෙන් සහ වස්තුව පිටපත් නොකිරීමෙන් ක්රමලේඛකයා දැනුවත් කළ හැකිය.
ඒවා මා විසින්ම ප්රකාශ කිරීමට අවශ්ය වන්නේ කවදාද?
තුන්වන රීතියේ සඳහන් වන්නේ ඔබ කිසිවක් ප්රකාශ කරන්නේ නම් a
එවිට ඔබ මේ තුනම ප්රකාශ කළ යුතුය. පිටපත් මෙහෙයුමක අර්ථය භාර ගැනීමේ අවශ්යතාවය සෑම විටම පාහේ කිසියම් ආකාරයක සම්පත් කළමනාකරණයක් සිදු කරන පන්තියෙන් පැන නැගී ඇති බව නිරීක්ෂණයෙන් එය වර්ධනය විය.
එක් පිටපත් මෙහෙයුමකදී සම්පත් කළමණාකරනය සිදු කරනු ලැබුවද අනෙක් පිටපත් මෙහෙයුමේදී සිදු කිරීමට අවශ්ය විය හැකිය
පංති විනාශ කරන්නා සම්පත් කළමනාකරණයට ද සහභාගී වේ (සාමාන්යයෙන් එය මුදා හැරීම). කළමනාකරණය කළ යුතු සම්භාව්ය සම්පත මතකය වන අතර මතකය කළමනාකරණය කරන සියලුම සම්මත පුස්තකාල පන්ති (උදා: ගතික මතක කළමනාකරණය කරන STL බහාලුම්) සියල්ලම “විශාල තුන” ප්රකාශයට පත් කරයි: පිටපත් මෙහෙයුම් සහ විනාශ කරන්නා යන දෙකම.
තුන්වන රීතියේ ප්රතිවිපාකය නම්, පරිශීලකයා විසින් ප්රකාශයට පත් කරන ලද ඩිස්ට්රැක්ටරයක් තිබීම පෙන්නුම් කරන්නේ සරල සාමාජික නැණවත් පිටපතක් පන්තියේ පිටපත් කිරීමේ මෙහෙයුම් සඳහා සුදුසු නොවන බවයි. එයින් ඇඟවෙන්නේ, පංතියක් විනාශකාරකයක් ප්රකාශ කරන්නේ නම්, පිටපත් මෙහෙයුම් ස්වයංක්රීයව ජනනය නොකළ යුතු අතර, ඔවුන් නිවැරදි දේ නොකරන නිසා ය. සී ++ 98 සම්මත කරන විට, මෙම තර්කනයේ වැදගත්කම සම්පූර්ණයෙන් අගය නොකෙරුණි, එබැවින් සී ++ 98 හි, පරිශීලක ප්රකාශිත ඩිස්ට්රැක්ටරයක පැවැත්ම පිටපත් මෙහෙයුම් උත්පාදනය කිරීමට සම්පාදකයින්ගේ කැමැත්ත කෙරෙහි කිසිදු බලපෑමක් ඇති කළේ නැත. සී ++ 11 හි එය දිගටම පවතී, නමුත් පිටපත් මෙහෙයුම් උත්පාදනය වන කොන්දේසි සීමා කිරීම නිසා බොහෝ උරුම කේතය බිඳ වැටෙනු ඇත.
මගේ වස්තූන් පිටපත් කිරීම වළක්වා ගන්නේ කෙසේද?
පිටපත් සාදන්නා සහ පිටපත් පැවරුම් ක්රියාකරු පුද්ගලික ප්රවේශ පිරිවිතරයක් ලෙස ප්රකාශ කරන්න.
class MemoryBlock
{
public:
//code here
private:
MemoryBlock(const MemoryBlock& other)
{
cout<<"copy constructor"<<endl;
}
// Copy assignment operator.
MemoryBlock& operator=(const MemoryBlock& other)
{
return *this;
}
};
int main()
{
MemoryBlock a;
MemoryBlock b(a);
}
C ++ 11 සිට ඔබට පිටපත් සාදන්නා සහ පැවරුම් ක්රියාකරු මකා දැමූ බව ප්රකාශ කළ හැකිය
class MemoryBlock
{
public:
MemoryBlock(const MemoryBlock& other) = delete
// Copy assignment operator.
MemoryBlock& operator=(const MemoryBlock& other) =delete
};
int main()
{
MemoryBlock a;
MemoryBlock b(a);
}
දැනට පවතින බොහෝ පිළිතුරු දැනටමත් පිටපත් සාදන්නා, පැවරුම් ක්රියාකරු සහ විනාශ කරන්නා ස්පර්ශ කරයි. කෙසේ වෙතත්, පශ්චාත් C ++ 11 හි, චලන අර්ථකථනය හඳුන්වාදීම මෙය 3 න් ඔබ්බට පුළුල් කළ හැකිය.
මෑතකදී මයිකල් ක්ලයිස් මෙම මාතෘකාවට ස්පර්ශ වන කතාවක් ඉදිරිපත් කළේය: http://channel9.msdn.com/events/CPP/C-PP-Con-2014/The-Canonical-Class
C ++ හි තුනේ රීතිය සැලසුමේ මූලික මූලධර්මයක් වන අතර පහත සඳහන් සාමාජික ශ්රිතයක පැහැදිලි අර්ථ දැක්වීමක් තිබේ නම් ක්රමලේඛකයා අනෙක් සාමාජිකයන් දෙදෙනාගේ ක්රියාකාරිත්වය එකට අර්ථ දැක්විය යුතුය. පහත සඳහන් සාමාජික කාර්යයන් තුන අත්යවශ්ය වේ: විනාශ කරන්නා, පිටපත් සාදන්නා, පිටපත් පැවරුම් ක්රියාකරු.
C ++ හි පිටපත් සාදන්නා විශේෂ ඉදිකිරීම්කරුවෙකි. එය නව වස්තුවක් තැනීමට භාවිතා කරයි, එය පවතින වස්තුවක පිටපතකට සමාන නව වස්තුවකි.
පිටපත් පැවරුම් ක්රියාකරු යනු විශේෂ පැවරුම් ක්රියාකරුවෙකු වන අතර එය සාමාන්යයෙන් පවතින වස්තුවක් එකම වර්ගයේ වස්තුවකට නියම කිරීමට භාවිතා කරයි.
ඉක්මන් උදාහරණ ඇත:
// default constructor
My_Class a;
// copy constructor
My_Class b(a);
// copy constructor
My_Class c = a;
// copy assignment operator
b = a;
c++-faq
ටැගය විකි ඔබ වසා ඡන්දය පෙර .