C++, ki melyik értékadási stílust preferálja és miért?
class MyClass_1
{
int m_data;
public:
MyClass_1() {};
~MyClass_1() {};
int GetData() const { return m_data; }
void SetData(const int& data) { m_data = data; }
};
class MyClass_2
{
int m_data;
public:
MyClass_2() {};
~MyClass_2() {};
int Data() const { return m_data; }
void Data(const int& data) { m_data = data; }
};
class MyClass_3
{
int m_data;
public:
MyClass_3() {};
~MyClass_3() {};
int Data() const { return m_data; }
int& Data() { return m_data; }
};
int main(int argc, char *argv[])
{
MyClass_1 mc_1;
int data_1 = mc_1.GetData();
mc_1.SetData(data_1 * 2);
MyClass_2 mc_2;
int data_2 = mc_2.Data();
mc_2.Data(data_2 * 2);
MyClass_3 mc_3;
int data_3 = mc_3.Data();
mc_3.Data() = data_3 * 2;
return 0;
}
Hát én rég C++-ztam, de ebből az első tűnik leginkább egyértelműnek.
A 3-as a C#-os propertyt próbálja utánozni, csak mondjuk nem tudom, hogy itt hogyan tudsz például Set-nél ellenőrizni vagy módosítani, így kb tök ugyanaz, mint egy publikus változó.
A 2-es nem rossz, de szerintem kevésbé olvashatóbb, mint az 1-es.
Tanulság: Mennyivel szebb a C# property. :)
Mindegyik példád rossz. Ne írj boilerplate code-ot! Semmilyen haszna nincsen, de fizetsz a használatáért. A fordítót függvényhívásokkal terheled ezekhez a triviális getter/setter párosokhoz. Ezek nem csak, hogy nem csökkentik a hozzáférést, de még triviálisak is. A jó getter setter-nek van tartalma, nem egy ilyen hülyeség.
OFF: A konstruktor destruktor definiálásodról nem is beszélve. Komolyan mondd el légyszíves minek írtál üres destruktort? Nézd át újra az objektumok életciklusának a kezelését, mert valami nagyon nincsen meg.
Tényleg én nem ismerem az inline függvényeket? :D Azt mondd meg, hogy a sokadik Get...().Get...() hívások után mikor nem inline-olódik tovább? Mi a határ, hány utasítás után áll le a fordítód? És egyetlen nem átlátszó hívásnál az inlining véget ér.
Tanuld meg inkább, hogy mikor kell konstruktort destruktort írni. Többre mész vele.
#1
Ha írsz a primitív típusokhoz egy wrapper classt akkor így:
template<typename T>
class PrivateMember
{
T m_data;
std::function<bool(const T& v)> m_pred;
public:
PrivateMember(const T& data, std::function<bool(const T& v)> pred) : m_data{data}, m_pred{pred} {}
~PrivateMember() {}
T& operator=(const T& rhs)
{
if(!m_pred(rhs))
return m_data = rhs;
throw std::exception{};
}
operator T() { return m_data; }
T& operator*=(const T& rhs) { T temp = m_data * rhs; if(!m_pred(temp)) return m_data = temp; throw std::exception{}; }
};
class MyClass_3
{
PrivateMember<int> m_data;
public:
MyClass_3() : m_data{5, [](const auto& i){return i < 0 || i > 10; }} {};
~MyClass_3() {};
const auto& Data() const { return m_data; }
auto& Data() { return m_data; }
};
int main(int argc, char *argv[])
{
MyClass_3 mc_3;
int data_3 = mc_3.Data();
mc_3.Data() *= 2; // OK
mc_3.Data() = data_3 * 3; // ERROR
std::getchar();
return 0;
}
#5
Nem fogom lemásolni, de ha érdekel:
Másrészt meg menj hangyákat szedni ahelyett, hogy leegyszerűsített példákba kötsz bele, mert komolyabb dolgokhoz tudatlan vagy.
OFF
"Mi a határ, hány utasítás után áll le a fordítód? És egyetlen nem átlátszó hívásnál az inlining véget ér."
Ha ilyen van, ott meg már rég nem ez a getter fog teljesítménybeli problémát okozni..
ON
Az első és második között lévő különbséget találgatom egy ideje, de nincs meg. (a név ne számítson már).
Inkább setter, mint ez a referencia dolog. De ha azt nézed, pl java-ban, a getterrel is csak referenciát tudsz adni, mondjuk egy List-nél, ki is van adva az egész, de ez nem feltétlen baj.
Az első és második közti különbség az olvashatóság.
Első verziónál nem egyértelmű, hogy az most értéket állít be, és nem kiszámít valamit amihez a 10-es számot használja fel.
rate(10) | setRate(10)
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!