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.
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've read the community wiki quetion about the 3 different conventions for accessor methods and was supmetwhat surprised not to see the following convention:
const unsigned& amount() const { return _amount; }
unsigned& amount() { return _amount; }
true, it's not quite the same as seamless as being able to avoid the parentheses altogether () - which would (I feel) be idea - but it's still something; right?
It defeats the purpose of accessors. If you provide the two
functions, you might as well make the data member public and be
done with it.
EDIT:
Just to make things perfectly clear: there are cases where
using a C style struct is the most appropriate solution. In
those cases, you make the data members public, and don't worry
about accessors. For classes with significant behavior, on the
other hand, you won't have accessors at all, or very few. For
the most part, the internal state is not reflected directly at
the public interface (and that state which is is usually read
only). About the only time you'd have need for accessors is for
classes which are basically data, but which must enforce
invariants across the data,
(And for what it's worth: if the data is logically an attribute
of the class, I use:
int amount() const { return myAmount; }
void amount( int newValue ) { myAmount = newValue; }
For getters of values which are not logically attributes,
however, I'll use getAmount().)
The second of your examples gives the user access to the original _amount in the class, without any form of protection from the class itself. The purpose of "encapsulation", which is an important aspect of OOP is to ensure that all the accesses to a variable is done within the class itself - that way the class can control the value range or other validity.
If you want the class to transparently allow the user to use amount, then call it amount and make it public. There is no need for accessor functions then.
The problem with this is that it can defeat the purpose of a getter/setter convention. If you're passing a mutable reference to the private member, you might as well expose the member and remove the hassle of function calls.
Also, I found this syntax very ugly and unreadable, but that's my personal taste:
foo.amount() = 23;
I have about 15~20 member variables which needs to be accessed, I was wondering
if it would be good just to let them be public instead of giving every one of them
get/set functions.
The code would be something like
class A { // a singleton class
public:
static A* get();
B x, y, z;
// ... a lot of other object that should only have one copy
// and doesn't change often
private:
A();
virtual ~A();
static A* a;
};
I have also thought about putting the variables into an array, but I don't
know the best way to do a lookup table, would it be better to put them in an array?
EDIT:
Is there a better way than Singleton class to put them in a collection
The C++ world isn't quite as hung up on "everything must be hidden behind accessors/mutators/whatever-they-decide-to-call-them-todays" as some OO-supporting languages.
With that said, it's a bit hard to say what the best approach is, given your limited description.
If your class is simply a 'bag of data' for some other process, than using a struct instead of a class (the only difference is that all members default to public) can be appropriate.
If the class actually does something, however, you might find it more appropriate to group your get/set routines together by function/aspect or interface.
As I mentioned, it's a bit hard to tell without more information.
EDIT: Singleton classes are not smelly code in and of themselves, but you do need to be a bit careful with them. If a singleton is taking care of preference data or something similar, it only makes sense to make individual accessors for each data element.
If, on the other hand, you're storing generic input data in a singleton, it might be time to rethink the design.
You could place them in a POD structure and provide access to an object of that type :
struct VariablesHolder
{
int a;
float b;
char c[20];
};
class A
{
public:
A() : vh()
{
}
VariablesHolder& Access()
{
return vh;
}
const VariablesHolder& Get() const
{
return vh;
}
private:
VariablesHolder vh;
};
No that wouldn't be good. Image you want to change the way they are accessed in the future. For example remove one member variable and let the get/set functions compute its value.
It really depends on why you want to give access to them, how likely they are to change, how much code uses them, how problematic having to rewrite or recompile that code is, how fast access needs to be, whether you need/want virtual access, what's more convenient and intuitive in the using code etc.. Wanting to give access to so many things may be a sign of poor design, or it may be 100% appropriate. Using get/set functions has much more potential benefit for volatile (unstable / possibly subject to frequent tweaks) low-level code that could be used by a large number of client apps.
Given your edit, an array makes sense if your client is likely to want to access the values in a loop, or a numeric index is inherently meaningful. For example, if they're chronologically ordered data samples, an index sounds good. Summarily, arrays make it easier to provide algorithms to work with any or all of the indices - you have to consider whether that's useful to your clients; if not, try to avoid it as it may make it easier to mistakenly access the wrong values, particularly if say two people branch some code, add an extra value at the end, then try to merge their changes. Sometimes it makes sense to provide arrays and named access, or an enum with meaningful names for indices.
This is a horrible design choice, as it allows any component to modify any of these variables. Furthermore, since access to these variables is done directly, you have no way to impose any invariant on the values, and if suddenly you decide to multithread your program, you won't have a single set of functions that need to be mutex-protected, but rather you will have to go off and find every single use of every single data member and individually lock those usages. In general, one should:
Not use singletons or global variables; they introduce subtle, implicit dependencies between components that allow seemingly independent components to interfere with each other.
Make variables const wherever possible and provide setters only where absolutely required.
Never make variables public (unless you are creating a POD struct, and even then, it is best to create POD structs only as an internal implementation detail and not expose them in the API).
Also, you mentioned that you need to use an array. You can use vector<B> or vector<B*> to create a dynamically-sized array of objects of type B or type B*. Rather than using A::getA() to access your singleton instance; it would be better to have functions that need type A to take a parameter of type const A&. This will make the dependency explicit, and it will also limit which functions can modify the members of that class (pass A* or A& to functions that need to mutate it).
As a convention, if you want a data structure to hold several public fields (plain old data), I would suggest using a struct (and use in tandem with other classes -- builder, flyweight, memento, and other design patterns).
Classes generally mean that you're defining an encapsulated data type, so the OOP rule is to hide data members.
In terms of efficiency, modern compilers optimize away calls to accessors/mutators, so the impact on performance would be non-existent.
In terms of extensibility, methods are definitely a win because derived classes would be able to override these (if virtual). Another benefit is that logic to check/observe/notify data can be added if data is accessed via member functions.
Public members in a base class is generally a difficult to keep track of.
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