I have a simple container class with a copy constructor.
Do you recommend using getters and setters, or accessing the member variables directly?
public Container
{
public:
Container() {}
Container(const Container& cont) //option 1
{
SetMyString(cont.GetMyString());
}
//OR
Container(const Container& cont) //option 2
{
m_str1 = cont.m_str1;
}
public string GetMyString() { return m_str1;}
public void SetMyString(string str) { m_str1 = str;}
private:
string m_str1;
}
In the example, all code is inline, but in our real code there is no inline code.
Update (29 Sept 09):
Some of these answers are well written however they seem to get missing the point of this question:
this is simple contrived example to discuss using getters/setters vs variables
initializer lists or private validator functions are not really part of this question. I'm wondering if either design will make the code easier to maintain and expand.
Some ppl are focusing on the string in this example however it is just an example, imagine it is a different object instead.
I'm not concerned about performance. we're not programming on the PDP-11
EDIT: Answering the edited question :)
this is simple contrived example to
discuss using getters/setters vs
variables
If you have a simple collection of variables, that don't need any kind of validation, nor additional processing then you might consider using a POD instead. From Stroustrup's FAQ:
A well-designed class presents a clean
and simple interface to its users,
hiding its representation and saving
its users from having to know about
that representation. If the
representation shouldn't be hidden -
say, because users should be able to
change any data member any way they
like - you can think of that class as
"just a plain old data structure"
In short, this is not JAVA. you shouldn't write plain getters/setters because they are as bad as exposing the variables them selves.
initializer lists or private validator functions are not really
part of this question. I'm wondering
if either design will make the code
easier to maintain and expand.
If you are copying another object's variables, then the source object should be in a valid state. How did the ill formed source object got constructed in the first place?! Shouldn't constructors do the job of validation? aren't the modifying member functions responsible of maintaining the class invariant by validating input? Why would you validate a "valid" object in a copy constructor?
I'm not concerned about performance. we're not programming on the PDP-11
This is about the most elegant style, though in C++ the most elegant code has the best performance characteristics usually.
You should use an initializer list. In your code, m_str1 is default constructed then assigned a new value. Your code could be something like this:
class Container
{
public:
Container() {}
Container(const Container& cont) : m_str1(cont.m_str1)
{ }
string GetMyString() { return m_str1;}
void SetMyString(string str) { m_str1 = str;}
private:
string m_str1;
};
#cbrulak You shouldn't IMO validate cont.m_str1 in the copy constructor. What I do, is to validate things in constructors. Validation in copy constructor means you you are copying an ill formed object in the first place, for example:
Container(const string& str) : m_str1(str)
{
if(!valid(m_str1)) // valid() is a function to check your input
{
// throw an exception!
}
}
You should use an initializer list, and then the question becomes meaningless, as in:
Container(const Container& rhs)
: m_str1(rhs.m_str1)
{}
There's a great section in Matthew Wilson's Imperfect C++ that explains all about Member Initializer Lists, and about how you can use them in combination with const and/or references to make your code safer.
Edit: an example showing validation and const:
class Container
{
public:
Container(const string& str)
: m_str1(validate_string(str))
{}
private:
static const string& validate_string(const string& str)
{
if(str.empty())
{
throw runtime_error("invalid argument");
}
return str;
}
private:
const string m_str1;
};
As it's written right now (with no qualification of the input or output) your getter and setter (accessor and mutator, if you prefer) are accomplishing absolutely nothing, so you might as well just make the string public and be done with it.
If the real code really does qualify the string, then chances are pretty good that what you're dealing with isn't properly a string at all -- instead, it's just something that looks a lot like a string. What you're really doing in this case is abusing the type system, sort of exposing a string, when the real type is only something a bit like a string. You're then providing the setter to try to enforce whatever restrictions the real type has compared to a real string.
When you look at it from that direction, the answer becomes fairly obvious: rather than a string, with a setter to make the string act like some other (more restricted) type, what you should be doing instead is defining an actual class for the type you really want. Having defined that class correctly, you make an instance of it public. If (as seems to be the case here) it's reasonable to assign it a value that starts out as a string, then that class should contain an assignment operator that takes a string as an argument. If (as also seems to be the case here) it's reasonable to convert that type to a string under some circumstances, it can also include cast operator that produces a string as the result.
This gives a real improvement over using a setter and getter in a surrounding class. First and foremost, when you put those in a surrounding class, it's easy for code inside that class to bypass the getter/setter, losing enforcement of whatever the setter was supposed to enforce. Second, it maintains a normal-looking notation. Using a getter and a setter forces you to write code that's just plain ugly and hard to read.
One of the major strengths of a string class in C++ is using operator overloading so you can replace something like:
strcpy(strcat(filename, ".ext"));
with:
filename += ".ext";
to improve readability. But look what happens if that string is part of a class that forces us to go through a getter and setter:
some_object.setfilename(some_object.getfilename()+".ext");
If anything, the C code is actually more readable than this mess. On the other hand, consider what happens if we do the job right, with a public object of a class that defines an operator string and operator=:
some_object.filename += ".ext";
Nice, simple and readable, just like it should be. Better still, if we need to enforce something about the string, we can inspect only that small class, we really only have to look one or two specific, well-known places (operator=, possibly a ctor or two for that class) to know that it's always enforced -- a totally different story from when we're using a setter to try to do the job.
Do you anticipate how the string is returned, eg. white space trimmed, null checked, etc.? Same with SetMyString(), if the answer is yes, you are better off with access methods since you don't have to change your code in zillion places but just modify those getter and setter methods.
Ask yourself what the costs and benefits are.
Cost: higher runtime overhead. Calling virtual functions in ctors is a bad idea, but setters and getters are unlikely to be virtual.
Benefits: if the setter/getter does something complicated, you're not repeating code; if it does something unintuitive, you're not forgetting to do that.
The cost/benefit ratio will differ for different classes. Once you're ascertained that ratio, use your judgment. For immutable classes, of course, you don't have setters, and you don't need getters (as const members and references can be public as no one can change/reseat them).
There's no silver bullet as how to write the copy constructor.
If your class only has members which provide a copy constructor that creates
instances which do not share state (or at least do not appear to do so) using an initializer list is a good way.
Otherwise you'll have to actually think.
struct alpha {
beta* m_beta;
alpha() : m_beta(new beta()) {}
~alpha() { delete m_beta; }
alpha(const alpha& a) {
// need to copy? or do you have a shared state? copy on write?
m_beta = new beta(*a.m_beta);
// wrong
m_beta = a.m_beta;
}
Note that you can get around the potential segfault by using smart_ptr - but you can have a lot of fun debugging the resulting bugs.
Of course it can get even funnier.
Members which are created on demand.
new beta(a.beta) is wrong in case you somehow introduce polymorphism.
... a screw the otherwise - please always think when writing a copy constructor.
Why do you need getters and setters at all?
Simple :) - They preserve invariants - i.e. guarantees your class makes, such as "MyString always has an even number of characters".
If implemented as intended, your object is always in a valid state - so a memberwise copy can very well copy the members directly without fear of breaking any guarantee. There is no advantage of passing already validated state through another round of state validation.
As AraK said, the best would be using an initializer list.
Not so simple (1):
Another reason to use getters/setters is not relying on implementation details. That's a strange idea for a copy CTor, when changing such implementation details you almost always need to adjust CDA anyway.
Not so simple (2):
To prove me wrong, you can construct invariants that are dependent on the instance itself, or another external factor. One (very contrieved) example: "if the number of instances is even, the string length is even, otherwise it's odd." In that case, the copy CTor would have to throw, or adjust the string. In such a case it might help to use setters/getters - but that's not the general cas. You shouldn't derive general rules from oddities.
I prefer using an interface for outer classes to access the data, in case you want to change the way it's retrieved. However, when you're within the scope of the class and want to replicate the internal state of the copied value, I'd go with data members directly.
Not to mention that you'll probably save a few function calls if the getter are not inlined.
If your getters are (inline and) not virtual, there's no pluses nor minuses in using them wrt direct member access -- it just looks goofy to me in terms of style, but, no big deal either way.
If your getters are virtual, then there is overhead... but nevertheless that's exactly when you DO want to call them, just in case they're overridden in a subclass!-)
There is a simple test that works for many design questions, this one included: add side-effects and see what breaks.
Suppose setter not only assigns a value, but also writes audit record, logs a message or raises an event. Do you want this happen for every property when copying object? Probably not - so calling setters in constructor is logically wrong (even if setters are in fact just assignments).
Although I agree with other posters that there are many entry-level C++ "no-no's" in your sample, putting that to the side and answering your question directly:
In practice, I tend to make many but not all of my member fields* public to start with, and then move them to get/set when needed.
Now, I will be the first to say that this is not necessarily a recommended practice, and many practitioners will abhor this and say that every field should have setters/getters.
Maybe. But I find that in practice this isn't always necessary. Granted, it causes pain later when I change a field from public to a getter, and sometimes when I know what usage a class will have, I give it set/get and make the field protected or private from the start.
YMMV
RF
you call fields "variables" - I encourage you to use that term only for local variables within a function/method
Related
I understand the reason why we should avoid using getters/setters, but I don't know how to avoid using them.
For example, I have three classes as follows,
A (private: point_B)
B (private: point_C)
C (private: val_C)
A has a private member point_B which is a pointer that points to B, and B also has a private member point_C which is a pointer that points to C. And C has a private int value val_C.
How can I access val_C in A?
Update:
In this case,
A is a class called state, which has the address point_B.
B is a class called node, which has a pointer call pointer_C.
C is a class called base_file, which has two derived classes called file and directory.
Update 2:
Ty guys for you help. Some of you are really trying to help instead of acting like someone who knows everything. I appreciate it.
Sry I can't post the whole assignment here since its too large even without documents. I'll post professor's answer here if you guys are interested tomorrow.
Update 3:
Please find reference here
The right thing to do is to leave the implementation to specify class.
Update 4:
The answer is to not to access private value in each class, but to implement functions to use them. That explains why making them private at the first place.
Maybe a little clarification is in order -- getters and setters aren't meant to be avoided at all costs; they have their place. The reason people say they should be avoided is because one goal of good object-oriented program design is encapsulation -- that is to say, each class should keep the details of its own implementation as private as possible, so that users of that class don't need to know (or care) about how the class was implemented. This becomes increasingly important as the program gets larger and more complicated, because a human programmer can only keep so many details in his/her head at once, and if the programmer has to remember everything about how class C works while simultaneously writing/debugging class A, that's an additional/unecessary cognitive burden that at some point will cause the programmer's brain to explode.
So, getting back to the main question -- how to avoid getters and setters -- the way to do it is to define your classes' interfaces at a higher level of abstraction than as simple repositories for state variables. (After all, if you wanted a simple collection of state variables, there's no reason to use a C++ class at all, you could simply declare a C-style struct instead)
For example, if your class C was intended to represent, say, a slot machine, a poor interface to class C might include lots of getters and setters, like this:
int getNumCoins() const {return numCoins;}
void setNumCoins(int newCoinCount) {numCounts = newCoinCount;}
void setDisplayedResult(const string & displayStr) {result = displayStr;}
int getDisplayedResult() const {return result;}
... and the poor programmer who was forced to use class C would have to write code like this:
playersWallet--; // take a coin out of the player's wallet
c.setNumCoins(c.getNumCoins()+1); // insert the coin into the machine
string newResult = "10 J A"; // somehow figure out what the machine should display
c.setDisplayedResult(newResult); // and make the machine display it
if (c.getDisplayedResult() == "7 7 7")
{
cout << "YOU ARE WINNER!" << endl;
int numCoinsWon = 5000; // jackpot!
c.setNumCoins(c.getNumCoins()-numCoinsWon); // deduct from machine's balance
playersWallet += numCoinsWon; // add to player's balance
}
[... and so on...]
Note that in the above code, the programmer had to think about all of the internal mechanisms of the slot machine, and write his own code to handle each step of its operation. With good encapsulation, on the other hand, the slot machine's public interface would be much simpler and more opaque, like this:
// returns the number of coins the player won on this round
int pullTheBigLever();
... and the programmer who was using this API might write code like this:
playersWallet += (c.pullTheBigLever() - 1); // -1 for the coin the player put in
Note that there is only one line of code, and that the programmer didn't have to think at all about how the internals of the slot machine worked. This avoids exploding-programmer-brain-syndrome, and just as importantly it means you (or someone else) can go back later and change the private implementation of how the slot machine works without breaking the code that interacts with the slot machine.
So when are getters and setters acceptable? Answer: when there really isn't any higher level of abstraction to be had. If you are writing a class that represents a light switch, then just being able to examine the switch's current position, or specify a new position for it, may be all the functionality you need. But in many (most?) cases you are implementing the functionality of something more complex than that, and the more of that complexity you can hide behind your public interface, the happier users of that class (including you) will be.
Short answers, in OOP, classes should have "properties" as part of their public API. Properties can have have things like getters, setters and change notifications, as appropriate. Wether a getter directly returns a private member variable, that is an implementation detail, and could change as needed. Distinguish the concept of property from the concept of member variable.
When thinking about it like this, the direct answer to your question is, that there's nothing you should try to "avoid", other than having unnecessary readable properties.
Note that often there is no explicit syntax or support for properties in an object oriented language (popular counter-example: C#), so it's easy to think they are same thing as a member variable with a setter and a getter. But the overlap is sort of a coincident, and not something you should care about when using a class. In a way, there is no getter for a member variable, there is only a getter for the property, even if it happens to map 1:1 with a member variable.
How avoid using getters/setters in C++.
To avoid setter/getter, all code that accesses a data attribute of class C, must be part of a class C method.
Alternate wording: bring the code that uses the data attribute inside the class.
update 2016/01/25
Would an example help? I find it trivial to avoid getters and setters (and public data and friends, etc.) I suppose I'm just used to it.
I recently completed yet another implementation of the game-of-life. The whole game is the entertainment value of watching the cells change patterns. Impressively complex behaviour from a small set of rules.
My class Cell_t has ONLY private data, No getters, no setters, and no friends. No other class has access to any cells data.
Here is a snippet of that part of my game illustrating how easy it is to live without getters, setters and friends creating the undesirable coupling and cohesion:
// somewhere in GameOfLife exists
std::vector<Cell_t> m_ptCellVec; // a vector of cell ptrs
GameOfLife::exec(...)
{
// ... preliminary stuff
do {
// ... some preliminary stuff
// NOTE 1
for ( auto it : m_ptCellVec ) it->countNeighbor();
// NOTE 2
for ( auto it : m_ptCellVec ) { it->updateDisplay();}
// .... more stuff
if(timeElapsed > timeLimit) break;
if(m_generation > genLimit) break;
}while(1);
}
NOTE 1 -- The class GameOfLife does not count neigbors ... each cell does its own counting. The next state is computed from these counts.
NOTE 2 -- The class GameOfLife does not update the display ... each cell updates it's own little piece of the screen.
THUS, there is no getter of Cell_t state, or next state, or living-neighbour count, or dead-neighbour count, etc.
With respect to this aspect of these two classes
The cohesion (of Cell_t) is functional, the most desirable.
The coupling (of GameOfLife_t to Cell_t) is 'none', also the most
desirable.
Changing the name or type of a Cell_t private data attribute has no
impact on any other code.
Oh, and a debug routine I often add (for another example):
std::string Cell_t dump() {
std::stringstream ss;
ss << // .... anything you want to 'dump' from this instance
return (ss.str());
}
I use the method name dump() to indicate an intent for a 'deeper' investigation of the activity of a specific Cell_t ... I have sometimes generated tabular data of state changes, with time stamps.
I often have a very similar method called show(), which typically provides a string for the user ...
These two examples, perhaps, illustrate the idea that a getter is simply bypassing an important aspect of the design process - naming what you are doing.
I believe the question stated in Problem could be modified. The question should not be "How can I avoid getters and setters?". This question is also related to other questions like "Should this method be a non-static member, static member, friend or helper?" or "Should this property be private or protected?". A better question to ask yourself is rather, "Who needs to access a particular property".
One way of writing classes which are easy to maintain is to limit the number of functions which have access to a specific property. This does not necessarily mean that no function should ever have access to a private property or that getters/setters should never be used. Take for example the class std::vector. Which can be simplified to something like this (with a lot of reservartions). The actual implementation of vector is normally much more sophisticated and may have different internal implementation but this simplified construction will be used to show a point.
template<class T, class Allocator<T> a = basic_allocator<T>>
class vector {
size_t sz;
size_t cap;
Allocator a;
T* elem;
// ... private methods
public:
// public methods and operators.
}
This class lets the developer access all elements in the internal array, where data is stored. This is done either via the operator [] (unchecked) or via the function at (checked). The developer have full rights to read or write to these elements. Without this access the vector class would be fairly useless and people would revert to use arrays instead. The class also provides getters to sz and cap via methods size() and capacity(). However sz and cap is otherwise seen as internal information and the developer is not allowed to change these directly. Instead the developer can use methods like push_back(), pop_back(), shrink_to_fit(), resize(), ... To add or remove data, manage allocated memory, etc ... The reason is that these operations requires some quite advanced memory handling and modifying these variables would cause leaks and/or crashes. Further, the developer does really not need to bother about these abstractions, since the developer only need the elements in the array.
So to conclude encapsulation is good and need to be considered. However this does not mean that the developer is never allowed to directly modify properties of some classes.
I was trying to write down some implementations for a couple of data structures that I'm interested in for a multithreaded / concurrent scenario.
A lot of functional languages, pretty much all that I know of, design their own data structures in such a way that they are immutable, so this means that if you are going to add value to an instance t1 of T, you really get a new instance of T that packs t1 + value.
container t;
container s = t; //t and s refer to the same container.
t.add(value); //this makes a copy of t, and t is the copy
I can't find the appropriate keywords to do this in C++11; there are keywords, semantics and functions from the standard library that are clearly oriented to the functional approach, in particular I found that:
mutable it's not for runtime, it's more likely to be an hint for the compiler, but this keyword doesn't really help you in designing a new data structure or use a data structure in an immutable way
swap doesn't works on temporaries, and this is a big downside in my case
I also don't know how much the other keywords / functions can help with such design, swap was one of them really close to something good, so I could at least start to write something, but apparently it's limited to lvalues .
So I'm asking: it's possible to design immutable data structure in C++11 with a functional approach ?
You simply declare a class with private member variables and you don't provide any methods to change the value of these private members. That's it. You initialize the members only from the constructors of the class. Noone will be able to change the data of the class this way. The tool of C++ to create immutable objects is the private visibility of the members.
mutable: This is one of the biggest hacks in C++. I've seen at most 2 places in my whole life where its usage was reasonable and this keyword is pretty much the opposite of what you are searching for. If you would search for a keyword in C++ that helps you at compile time to mark data members then you are searching for the const keyword. If you mark a class member as const then you can initialize it only from the INITIALIZER LIST of constructors and you can no longer modify them throughout the lifetime of the instance. And this is not C++11, it is pure C++. There are no magic language features to provide immutability, you can do that only by programming smartly.
In c++ "immutability" is granted by the const keyword. Sure - you still can change a const variable, but you have to do it on purpose (like here). In normal cases, the compiler won't let you do that. Since your biggest concern seems to be doing it in a functional style, and you want a structure, you can define it yourself like this:
class Immutable{
Immutable& operator=(const Immutable& b){} // This is private, so it can't be called from outside
const int myHiddenValue;
public:
operator const int(){return myHiddenValue;}
Immutable(int valueGivenUponCreation): myHiddenValue(valueGivenUponCreation){}
};
If you define a class like that, even if you try to change myHiddenValue with const_cast, it won't actually do anything, since the value will be copied during the call to operator const int.
Note: there's no real reason to do this, but hey - it's your wish.
Also note: since pointers exist in C++, you still can change the value with some kind of pointer magic (get the address of the object, calc the offset, etc), but you can't really help that. You wouldn't be able to prevent that even when using an functional language, if it had pointers.
And on a side note - why are you trying to force yourself in using C++ in a functional manner? I can understand it's simpler for you, and you're used to it, but functional programming isn't often used because of its downfalls. Note that whenever you create a new object, you have to allocate space. It's slower for the end-user.
Bartoz Milewski has implemented Okasaki's functional data structures in C++. He gives a very thorough treatise on why functional data structures are important for concurrency. In that treatise, he explains the need in concurrency to construct an object and then afterwards make it immutable:
Here’s what needs to happen: A thread has to somehow construct the
data that it destined to be immutable. Depending on the structure of
that data, this could be a very simple or a very complex process. Then
the state of that data has to be frozen — no more changes are
allowed.
As others have said, when you want to expose data in C++ and have it not be available for changing, you make your function signature look like this:
class MutableButExposesImmutably
{
private:
std::string member;
public:
void complicatedProcess() { member = "something else"; } // mutates
const std::string & immutableAccessToMember() const {
return member;
}
};
This is an example of a data structure that is mutable, but you can't mutate it directly.
I think what you are looking for is something like java's final keyword: This keyword allows you to construct an object, but thereafter the object remains immutable.
You can do this in C++. The following code sample compiles. Note that in the class Immutable, the object member is literally immutable, (unlike what it was in the previous example): You can construct it, but once constructed, it is immutable.
#include <iostream>
#include <string>
using namespace std;
class Immutable
{
private:
const std::string member;
public:
Immutable(std::string a) : member(a) {}
const std::string & immutable_member_view() const { return member; }
};
int main() {
Immutable foo("bar");
// your code goes here
return 0;
}
Re. your code example with s and t. You can do this in C++, but "immutability" has nothing to do with that question, if I understand your requirements correctly!
I have used containers in vendor libraries that do operate the way you describe; i.e. when they are copied they share their internal data, and they don't make a copy of the internal data until it's time to change one of them.
Note that in your code example, there is a requirement that if s changes then t must not change. So s has to contain some sort of flag or reference count to indicate that t is currently sharing its data, so when s has its data changed, it needs to split off a copy instead of just updating its data.
So, as a very broad outline of what your container will look like: it will consist of a handle (e.g. a pointer) to some data, plus a reference count; and your functions that update the data all need to check the refcount to decide whether to reallocate the data or not; and your copy-constructor and copy-assignment operator need to increment the refcount.
I know it is considered a bad idea to have public fields in your class. But what's the best approach when your class includes numerous hierarchical data structures and fields? For example:
class A {B d1; C d2; D d3;}
class B {E d4; F d5;}
class E {G d6; int d7;}
In C it is quite easy to access such a data structure, e.g. ptr_to_A->d1.d4.d7 and so on... But what's the approach when we use setters/getters?
When using setters and getters in C++, expressions like A.get_d1().get_d4().get_d7() don't seem convenient, and they force returning references. Since some structures are pretty big, returning by value seems a terrible idea.
Which approach or coding style do you use in these cases? Maybe getting rid of setters/getters and making these fields public?
I know it is considered a bad idea to have public fields in your class.
This is a sweeping statement that has come from last decade's Java development. You should be considering whether a member should be public or private on a member-by-member basis. There are times when a public data member is the right idea. Consider the following questions:
Do I need to maintain an invariant over this member?
Can this member have an invalid value?
Do I want the interface to give an alternate representation of this member?
If the answer to any of the above questions is yes, you probably want to use a getter.
Also consider whether it actually makes sense to set members individually. Perhaps you should be setting members with the constructor, and you want to provide some other interface that modifies those members.
When using setters and getters in C++, expressions like A.get_d1().get_d4().get_d7() don't seem convenient
While it's not too uncommon to have fairly deep nesting of data structures, usually a specific piece of code shouldn't have to delve too far into it. If it does, I imagine it's probably doing more than it should, going beyond its single responsibility. However, if it is a common task to get d7 from an A object, perhaps A should expose it in its interface:
int A::get_d7 {
return get_d1().get_d4().get_d7();
}
Since some structures are pretty big, returning by value seems a terrible idea.
Actually, with modern C++, this is not a problem at all. Passing by value should be considered your default mode of object passing. This is because temporary objects can now be moved from, which is essentially a very efficient form of copying.
In my coding style, a class should not expose public "raw" data members, but only getters and setters (even if they are simple one-line methods).
This is because the code can be upgraded in the future, and the single-line method can be expanded to something more complicated (or some debug-only builds features can be added to check some invariants, etc.), so it's better to keep the interface consistent for the clients (which is not possible if you expose "raw" data members).
You can avoid using the get_() prefix, and just consider the data member as a "property" with a simple (without get_...) name, e.g.
class Shape
{
public:
....
COLORREF Color() const // Just Color() i.e. the property name, without get_...
{
return m_color;
}
private:
COLORREF m_color;
};
And write client code like:
Shape s;
COLORREF someColor = s.Color();
which looks fine to me.
For the setter you can use a syntax like:
Shape& Color(COLORREF color)
{
m_color = color;
return *this;
}
and write client code like:
Shape s;
s.Color(...).Draw(); // set color and draw shape
If the type of the property is something more complex than a COLORREF (which is a 32-bit DWORD), you can use a pattern like:
std::wstring Name() const // getter
{
return m_name;
}
Shape& Name(std::wstring name) // setter
{
// Pass by value and move from the value (C++11 move semantics)
m_name = std::move(name);
return *this;
}
If you are just using a class as a pure data structure, and there is no behavior relating to that data that you want to encapsulate, then use a struct instead and access the fields directly. Bjarne Stroustrup recommends this approach. This is equivalent to using a class and declaring all the members as public, but calling it a struct instead makes it clearer that it is nothing more than simple collection of data.
If you are doing more than just storing data, then use getters and setters.
When using setters and getters in C++, expressions like
A.get_d1().get_d4().get_d7() don't seem convenient, and they force
returning references. Since some structures are pretty big, returning
by value seems a terrible idea.
No, you can choose whether to return by reference or by value.
I'm learning C++ and want to implement a custom string class, MyTextProc::Word, to add some features to std::string, such as string reversal, case conversion, translations etc.
It seems that this is best done using an is-a relationship:
namespace MyTextProc {
class Word : public string {
/* my custom methods.... */
};
}
I do not specify any constructors for my class but the above definition of the Word class only exposes default void and copy constructors - cant Word just inherit all the public string constructors as well?
It would be good to have Word work just like a string. I am adding no properties to string; must I really implement every single constructor of string, the base class, in order to implement my new subclass?
Is this best done using a has-a relationship? Should I just implement a const string& constructor and require clients to pass a string object for construction? Should I override all of the string constructors?
Welcomne to the C++ hell.
You've just touched one of the most controversial aspect of C++: std::string is not polymorphic and constructors are not inherited.
The only "clean" way (that will not make any sort of criticism) is embed std::string as a member, delegating ALL OF ITS METHODS. Good work!
Other ways can come around, but you have always to take care some limitations.
std::string has no virtual methods, so if you derive it, you will not get a polymorphic type.
That means that if yoy pass a Word to a sting keeping function, and that function calls a string method, your override method will not be called and
whatever allocation of Word via new must not be given to a string*: deleting via such pointer will result in undefined behavior
All the inherited method that take string and return string-s will work, but they'll return string, not Word.
About constructors, they are NOT INHERITED. The default construction inheritance is an illusion, due to the compiler synthesized default implementation of default, copy and assign, that call implicitly the base.
In C++11 a workaround can be
class Word: public std::string
{
public:
template<class... Args>
Word(Args&&... args) :std::string(std::forward<Args>(args)...)
{}
//whatever else
};
This makes whatever kind of arguments to be given in a call to a suitable std::sting ctor (if it exist, otherwise a compile error happens).
Now, decide yourself what the design should be. May be you will come with normal std::string and an independent set of free functions.
Another (imperfect) way can be make Word not inheriting, but embedding std::string, constructed as above, and implicitly convertible into std::string. (plus having a str() explicit method). This let you able to use a Word as a string, create a Word from a string, but not use a Word "in place of" a string.
Another thing to unlearn (may be from Java ...): don't fix yourself to "is-a = inheritance and has-a = embedding" OOP rule. All C++ standard library objects are not Objects in OOP sense, so all the OOP school methodologies have fallacies in that context.
You have to decide in you case what is the trade-off between simple coding (and good application of the "don't repeat yourself" paradigm, much easier with imheritance) or simple maintenance (and embedding let your code less prone to be used wrongly by others)
This is in answer t othe comment below:
"the lack of polymorphism of standard C++ classes. Why is this so? It seems to a novice like me that not implementing std C++ libs using virtual functions is defeating the point of the language they are designed to enrich!!!"
Well ... yes and not!
Since you cite PERL, consider that
- PERL is a scripting language, where types are dynamic.
- Java is a language where types are static and objects dynamic
- C++ is a language where types are static and object are static (and dynamic allocation of object is explicit)
Now, in Java objects are always dynamically allocated and local variables are "reference" to those objects.
In C++, local variables are object themselves, and have value semantics. And the C++ standard library is designed not as a set of bases to extend, but as a set of value types for which generate code by means of templates.
Think to an std::string as something working just like int works: do you expect to derive from int to get "more methods" or to change the behavior of some of them?
The controversial aspect, here, is that -to be coherent with this design- std::string should just manage its internal memory, but should have no methods. Istead, string functions shold have been implemented as templates, so that they can be used as "algorithm" with whatever other class exhibiting a same std::string external behavior. Something the designers didn't.
They placed many methods on it, but they din't make it polymorphic to still retain the value semantics, thus making and ambiguous design, and retaining to inheritance the only way to "reuse" those methods without re-declaring them. This is possible, but with the limitation I told you.
If yo uwant to effectively create new function, to have "polymorphism on value", use teplates: intead of
std::string capitalize(const std::string& s) { .... }
do something like
template<class String>
String capitalize(const String& s) { .... }
So that you code can work with whatever class having the same string interface respect to characters, for whatever type of characters.
As honest advise, I'd implement the methods you want as functions which take in a string and return a string. They'll be easier to test, decoupled, and easy to use. When in C++, don't always reach for a class when a function would do. In fact, when you get into templates, you could create a templated function without definition and a specialization for the basic string class. That way, you always will know if the string type you're touching has a custom defined method (and yes, if you interact with Microsoft you'll discover there's 50 million string implementations.)
Okay, just about everywhere I read, I read that getters/setters are "evil".
Now, as a programmer who uses getters/setters often in PHP / C#, I do not see how they are alive. I have read that they break encapsulation, etc etc, however, here is a simple example.
class Armor{
int armorValue;
public:
Armor();
Armor(int); //int here represents armor value
int GetArmorValue();
void SetArmorValue(int);
};
Now, lets say getters and setters are "evil".
How are you supposed to change a member variable after initialization.
Example:
Armor arm=Armor(128); //armor with 128 armor value
//for some reason I would like to change this armor value
arm.SetArmorValue(55); //if i do not use getters / setters how is this possible?
Lets say the above is not okay, for whatever reason.
What if my game restricts armor values from 1 to 500. (No armor can have a piece that has more than 500 armor or less than 1 armor).
Now my implementation becomes
void Armor::SetArmor(int tArmValue){
if (tArmValue>=1 && tArmValue<=500)
armorValue=tArmValue;
else
armorValue=1;
}
So, how else would I impose this restriction without using getters/setters?
How else would I modify a property without using getters/setters?
Should armorValue just be a public member variable in case 1, and the getters/setters used in case 2?
Curious. THanks guys
You have misunderstood something. Not using getters/setters breaks encapsulation and exposes implementation details, and can be considered "evil" for some definition of evil.
I guess they can be considered evil in the sense, that without proper IDE/editor support, they are somewhat tediois to write in C++...
One pitfall of C++ is to create non-const reference getter, which allows also modification. That's same as returning a pointer to internal data, and will lock that part of internal implementation, and is really no better than making field public.
Edit: based on comments and other answers, what you heard probably refers to always creating non-private getter and setter for every field. But I would not call that evil either, just stupid ;-)
Being slightly contrarian: yes, getters and setters (aka accessors and mutators) are mostly evil.
The evil here is not, IMO, so much from "breaking encapsulation", as from simply defining a variable to be of one type (e.g., int) when it's really not that type at all. Looking at your example, you're calling Armor an int, but it's really not. While it's undoubtedly an integer, it's certainly not an int, which (among other things) defines a range. While your type is an integer, it's never intended to support the same range as an int at all. If you want Armor to be of a type integer from 1 to 500, define a type to represent that directly, and define Armor as an instance of that type. In this case, since the invariant you want to enforce is defined as part of the type itself, you don't need to tack a setter onto it to try to enforce it.
template <class T, class less=std::less<T> >
class bounded {
const T lower_, upper_;
T val_;
bool check(T const &value) {
return less()(value, lower_) || less()(upper_, value);
}
void assign(T const &value) {
if (check(value))
throw std::domain_error("Out of Range");
val_ = value;
}
public:
bounded(T const &lower, T const &upper)
: lower_(lower), upper_(upper) {}
bounded(bounded const &init)
: lower_(init.lower), upper_(init.upper), val_(init.val_)
{ }
bounded &operator=(T const &v) { assign(v); return *this; }
operator T() const { return val_; }
friend std::istream &operator>>(std::istream &is, bounded &b) {
T temp;
is >> temp;
if (b.check(temp))
is.setstate(std::ios::failbit);
else
b.val_ = temp;
return is;
}
};
With this in place, defining some armor with a range of 1..500 becomes utterly trivial:
bounded<int> armor(1, 500);
Depending on the situation, you might prefer to define (for example) a saturating type where attempting to assign an out of range value is fine, but the value that actually is assigned will simply be the nearest value that is within range.
saturating<int> armor(1, 500);
armor = 1000;
std::cout << armor; // prints "500"
Of course, what I've given above is also a bit bare-bones. For your armor type, it would probably be convenient to support -= (and possibly +=) so an attack would end up something like x.armor -= 10;.
Bottom line: the (or at least "one") major problem with getters and setters is that they usually point to your having defined a variable as being of one type when you really want some other type that happened to be sort of similar in a few ways.
Now, it's true that some languages (e.g., Java) fail to provide the programmer with the tools necessary to write code like that. Here I'm trusting your use of the C++ tag to indicate that you really do want to write C++ though. C++ does provide you with the necessary tools, and (at least IMO) your code will be better off for your making good use of the tools it provides so your type enforces the required semantic constraints while still using clean, natural, readable syntax.
In short: they aren't evil.
It's nothing wrong with them as long as they don't leak out the internal representation. I see no problems here.
A common criticism of get/set functions is that they can be abused by client code to perform operations that logically should be encapsulated in the class. For example, say a client wants to "polish" their armour, and decides the effect is to increase "value" by 20, so they do their little get and set thing and are happy. Then someone other client code elsewhere decides rusty armour should drop the value by 30, and they do their bit. Meanwhile, a dozen other places in client code are also allowing polishing and rusting effects on armour - as well as say "reinforcing" and "cracking", and implementing them directly. There's no central control of this... the maintainer of the armour class has no ability to do things like:
have the rust, polish, reinforce and crack effects apply at most once per piece of armour
tune the number added to or subtract from value for specific logical effects
decide that the new "leather" armour type can't rust, and ignore client attempts to make it do so
On the other hand, if the first client that wanted to make armour rusty couldn't do so through the interface, they'd go to the maintainer of the armour class and say "hey, give me a function to do this", then other people could start using the logical-level "rust" operation, and if it became useful later to do the kinds of things I describe above they could be implemented easily and centrally in the armour class (e.g. by having a separate boolean to say if the armour was rusty, or a separate variable recording the rust effect).
So, the thing with get/set functions is they frustrate the natural evolution of an API of logical functionality, instead distributing logic throughout client code, leading in extremis to an unmaintainable mess.
Your getter/setter looks ok.
The alternative to getter/setters is to make member variables public. To be more precise, group variables into structure without member functions. And operate on this structure within your class
Giving access to members reduces encapsulation, but sometimes it's necessary. And the best way to do it is by means of getters and setters. Some people implement them when no such access is necessary, just because they can and it's a habit.
Getters are evil whenever:
They access directly data members of the class
When you have to add new getter every time you add data to the class
The data behaviour is different in each getter
Good getters would thus do the following:
They forward the request to some other object or collect the data from several places
You can fetch large amounts of data using just one getter
All the data you fetch is handled the same way
Setters on the other hand are evil always.
how else would I impose this restriction without using getters/setters? How else would I modify a property without using getters/setters?
You can check what you read from the variable and if its value is out of range use a predefined value instead (if possible).
You can also resort to dirty hacks such as protecting the memory underneath the variable from writing, catching write attempts and disallowing/ignoring the ones with invalid values. This is going to be cumbersome to implement and expensive to execute. It may be useful for debugging, though.