I have a class:
class A
{
private:
ComplexClass member1;
public:
getMember1(){return member1;};
};
and I have an implementation that, for code simplification (more easily understandable), needs to retrieve that member1 to work with it. The first thing that would come to my mind would be:
ComplexClass *myComplexClass = &getMember1();
myComplexClass.getSomething();
myComplexClass.getSomethingElse();
etc.
which is obviously not correct since I'm retrieving a pointer from a new object and not from member1 (and gets a compiler warning).
My question is: what is the best design to do things like this? How do I keep encapsulation and yet facilitate the access of a members using a pointer to it? (I only want to read from member1, not to write on it).
Should I make a
ComplexClass *getPointerToMember1()
inside the class A?
A const reference will keep them from editing. In my opinion, it makes your intention clearer than a const pointer.
class A
{
private:
ComplexClass member1;
public:
const ComplexClass &getMember1(){return member1;};
};
You're returning the member by value which makes a copy of the ComplexClass member. Thus you aren't working on the actual member when you call the subsequent methods (and what the compiler is telling you).
I think the more idiomatic C++ approach that helps maintain encapsulation and reduces coupling is to create an algorithmic member:
A::doStuff()
{
member1.getSomething();
member1.getSomethignElse();
}
This way anyone that uses class A doesn't care that the implementation uses a ComplexClass but instead just knows that they can tell A to do some work and it will get done in the best possible way.
EDIT for comment: In that case, I would suggest creating methods in A that get the values from ComplexClass (again to hide your implementation). If that's not suitable, then you could return the implementation by const reference: const ComplexClass& getMember1() const { return member1; }
Related
Classic way to get a reference to class member or its value we use getters like getValue(). Could this be an alternative way? :
class A{
ComplexClass value_;
public:
//No need. ComplexClass const& getValue() const { return value_; }
ComplexClass const& value = value_; /// ???
}
Will this work? How do you like such syntax?
UPD.
This point is to make user code simpler. Personally I better like auto x = a.value than auto x = a.getValue(). Of course this is a deal of taste.
Will this still work nice if:
class A{
public:
ComplexClass const& value = value_;
protected:
ComplexClass value_;
}
I ask because I met some troubles with one compiler.
One of the main reasons to prefer member functions over data members is flexibility and maintainability. If you only ever wrote some code once, perfectly, and it would never be changed or reused, then you could certainly have public data members that users refer to directly.
The interesting question is what happens when your code doesn't meet these criteria, e.g. if it is going to evolve, and if other people start using it. Then once you have a public data member, you are forced to always have that data member. Details of your class layout are now part of your public contract. Simple refactorings like moving common parts into nested member objects are no longer private and break existing users.
Your proposed reference data member adds almost no benefit over a public data member (except for in very trivial cases), and unlike member functions, non-static data members affect the class layout. Class layout is another thing you will probably want to keep stable once you have users, so that old, compiled libraries can continue to be linked against new user code. Member functions are much easier to evolve while keeping the data layout unchanged.
There's a nice example in the standard library where such a mistake was made: std::pair<T1, T2> is specified to contain public data members first and second. That means that all user specializations must adhere to the same specification, and cannot easily employ things like base layout optimizations. Had first and second been specified as member functions, such optimizations could be applied trivially.
My C++ project is getting huge. In some situations I'm passing arguments by reference just for my own convenience, in some I don't. Here's an example:
struct foo{
foo(int &member){
this->member = &member;
}
private:
int *member;
};
I'm using this pattern when I don't want to create two instances of the int variable. I don't have to implement the get or modify methods to manipulate its value. Instead I can change the variable without even accessing the foo object. However sometimes I'm using a different way of managing the member variables:
struct foo{
foo(int member){
this->member = member;
}
void modify_member(){
this->member = 6;
}
int get_member(){
return this->member;
}
private:
int member;
};
I'm not sure whether mixing these two methods of managing members in the same struct is a good practice. Should I normalize it? So for example EVERY function in the given struct will be using the "pass by value" method?
Your first case is a recipe for disaster. You'll end up with dangling pointers and a truck load of undefined behaviour.
Your second case is a poor attempt at encapsulation. There's no need for it. Just use the int. That will reduce the size of your code base.
Code should be simple to read and simple to change, that is in a way that does not break your program. Example one will lead to code, where you can hardly tell where foo instances are altered. Not to forget all the others issues mentioned already.
Example two is okay. In general, providing getters and setters let you add constraints later such as checking value ranges. So I recommend using them, unless you have good reasons not to do so. It also makes refactoring easier.
When passing parameters in a function: As a rule of thumb use pass by value in case of primitive types: int, double, etc.. When passing objects use constant References foo(const MyClass &myClass).
class MyClass {
public:
MyClass(const MyOtherClass &member1, int member2){
this->member1 = member1;
this->member1 = member1;
}
// other functions, getters, setters omitted...
private:
MyOtherClass member1;
int member2;
};
I'm curious if that's proper way of assignement
class Foo {
int x_;
public:
int & x() {
return x_;
}
};
My teacher is making assignement like that: obj.x() = 5;
But IMO that's not the proper way of doing it, its not obvious and it would be better to use setter here. Is that violation of clear and clean code ? If we take rule that we should read the code like a book that code is bad, am I right ? Can anyone tell me if am I right ? :)
IMO, this code is not a good practice in terms of evolution. If you need to provide some changes checking, formatting, you have to refactor your class API which can become a problem with time.
Having set_x() would be a way cleaner. Moreover, it will allow you to have checking mechanics in your setter.
a proper getter get_x() or x() could also apply some logic (format, anything...) before returning. In your case, you should return int instead of int& since setter should be used for modification (no direct modification allowed).
And truly speaking, this code doesn't really make sense... it returns a reference on a property making it fully modifiable. Why not having directly a public property then ? And avoid creating an additional method ?
Do you want control or not on your data? If you think so, then you probably want a proper getter and setter. If not, you probably don't need a method, just make it public.
To conclude, I would say you are right, because the way you see it would make it better over the time, prone to non-breaking change, better to read.
As the UNIX philosophy mentions : "Rule of Clarity: Clarity is better than cleverness."
Assuming that x() happens to be public (or protected) member the function effectively exposes an implementation: the is an int held somewhere. Whether that is good or bad depends on context and as it stands there is very little context.
For example, if x() were actually spelled operator[](Key key) and part of a container class with subscript operator like std::vector<T> (in which case Key would really be std::size_t) or std::map<Key, Value> the use of returning a [non-const] reference is quite reasonable.
On the other hand, if the advice is to have such functions for essentially all members in a class, it is a rather bad idea as this access essentially allows uncontrolled access to the class's state. Having access functions for all members is generally and indication that there is no abstraction, too: having setters/getters for members tends to be an indication that the class is actually just an aggregate of values and a struct with all public members would likely serve the purpose as well, if not better. Actual abstractions where access to the data matters tend to expose an interface which is independent of its actual representation.
In this example, the effect of returning a (non-const) reference is the same as if you made the variable public. Any encapsulation is broken. However, that is not a bad thing by default. A case where this can help a lot is when the variable is part of a complicated structure and you want to provide an easy interface to that variable. For example
class Foo {
std::vector<std::list<std::pair<int,int>>> values;
public:
int& getFirstAt(int i){
return values[i].[0].first;
}
};
Now you have an easy access to the first element of the first element at position i and dont need to write the full expression every time.
Or your class might use some container internally, but what container it is should be a private detail, then instead of exposing the full container, you could expose references to the elements:
class Bar {
std::vector<int> values; // vector is private!!
public:
int& at(int i){ // accessing elements is public
return values.at(i);
}
};
In general such a code confuses readers.
obj.x() = 5;
However it is not rare to meet for example the following code
std::vector<int> v = { 1, 0 };
v.back() = 2;
It is a drawback of the C++ language.
In C# this drawback was avoided by introducing properties.
As for this particular example it would be better to use a getter and a setter.
For example
class Foo {
int x_;
public:
int get_value() const { return x_; }
void set_value( int value ) { x_ = value; }
};
In this case the interface can be kept while the realization can be changed.
Let's say that I create a class where the primary use case will have the user always calling methods that modify its members. Or, looking at it another way, creating a class where every method will modify a class member(s).
For example, let's work with this dummy class:
class Foo
{
public:
void setM_1(int);
void setM_2(char);
void setM_3(float);
private:
int m_1;
char m_2;
float m_3;
};
For this Foo class, creating a const instance of it doesn't make sense, since every method is guaranteed to modify a member.
My goal is this: define this class in such a way that const-ly instantiating this class would have no effect. That is to say, a const Foo instance would be able to call every method that a Foo instance can.
I was able to achieve this behavior by marking every method const, declaring all non-const members mutable, and providing a ctor that initialized all members of the class.
So the const-ignorant version of Foo looks like:
class Foo
{
public:
Foo()
{
m_1 = 0;
m_2 = '\0';
m_3 = 0.0f;
}
void setM_1(int) const;
void setM_2(char) const;
void setM_3(float) const;
private:
mutable int m_1;
mutable char m_2;
mutable float m_3;
};
My question is this: is there a more elegant way of doing this?
Or, is this just bad class design? (no debates please).
After Answer Edit:
It's official: I just took a brain crap.
Kerrek SB is right: creating a const Foo and using class-modifying methods would raise compiler errors anyways, so my "const-ignorant" Foo is pointless.
A little documentation would solve my "problem".
No wonder I had a hunch that this was terrible class design.
Excuse me everyone, this question must've been an eyesore. Thank you for the constructive criticism.
Your goal is fundamentally incorrect. const exists not for funsies, but because it means that you really need const. Such a class would break horribly as e.g. a set key- where mutating it would break the ordering. There are other pitfalls like what happens when you provide it as a temporary in certain cases.
If your class cannot be realistically used in a const way, the interface should not lie about it and pretend that it's const when it isn't.
As for your question about bad design, I can safely say that yes, this sounds like a truly terrible design.
No, thank frak.
This makes no sense and would be extremely confusing/dangerous.
If you don't think it makes sense to have a const T then don't instantiate a const T.
From a language point of view, what bad things will happen if a class cannot be const:
First of all, is it that declaring an L-value of type const for it is not allowed, or that const references to it are also prohibited?
If you do not have const reference, then you won't have the default copy constructor, or copy assignment operator. You can't have the class be a member of any other class either, unless that also cannot be const.
I have seen some (sloppy) code where people implement iterators, and because they get tired of writing boilerplate, they implement const_iterators by const_casting away the const and using the non-const iterator implementation. They do this with classes that they know won't "actually" be const, so it won't be undefined behavior in their program. Potentially, not much fun for maintainers though.
For these classes, the class "cannot be const" in the sense that if you actually created a const one on the stack and used it normally you could technically get UB.
If what you want is for the compiler to complain when someone creates a const instance of some class, I think that doesn't really make sense. Const is fundamentally a "promise not to change something". Why would you want to forbid the programmer from making a promise about how he will use something, that seems only beneficial.
In C++ is always better to keep data of a class as private members.
If a class has a vector as member is better to put it as a private or public member?
If I have a vector as private member I cannot easily access to the member function of the vector. So I have to design the class with a method for every function I need to access the vector methods?
Example given:
class MyClass{
private:
std::vector<int> _myints;
public:
get_SizeMyints(){return _myints.size();}
add_IntToMyints(int x){_myints.push_back(x));
};
or is better to keep the vector public and call MyClass._myints.push_back(x)?
---------------------edit--------------
and just for clarity for what is needed this question:
snake.h:
enum directions{UP, DOWN, RIGHT, LEFT, IN, OUT, FW, RW };
class Snake
{
private:
enum directions head_dir;
int cubes_taken;
float score;
struct_color snake_color;
V4 head_pos;
public:
std::vector<Polygon4> p_list; //the public vector which should be private...
Snake();
V4 get_head_pos();
Polygon4 create_cube(V4 point);
void initialize_snake();
void move(directions);
void set_head_dir(directions dir);
directions get_head_dir();
void sum_cubes_taken(int x);
int get_cube_taken();
void sum_score(float x);
float get_score();
void set_snake_color();
};
so now I know how to change the code.
btw... a question, if I need to copy the vector in an other class like this: GlBox.p_list = Snake.p_list (works if are private) what will be an efficent method if they where private?
Running a for cycle to copy the the elements and pusshing back them in the GLBox.p_list seems a bit inefficent to me (but may be just an impression) :(
If it doesn't matter if someone comes along and empties the vector or rearranges all it's elements, then make it public. If it matters, then yes, you should make it protected/private, and make public wrappers like you have. [Edit] Since you say "it's a snake", that means it'd be bad if someone came and removed or replaced bits. Ergo, you should make it protected or private. [/Edit]
You can simplify a lot of them:
MyClass {
private:
std::vector<int> _myints;
public:
const std::vector<int>& get_ints() const {return _myints;}
add_IntToMyints(int x){_myints.push_back(x));
};
That get_ints() function will allow someone to look at the vector all they want, but won't let them change anything. However, better practice is to encapsulate the vector entirely. This will allow you to replace the vector with a deque or list or something else later on. You can get the size with std::distance(myobj.ints_begin(), myobj.ints_end());
MyClass {
private:
std::vector<int> _myints;
public:
typedef std::vector<int>::const_iterator const_iterator;
const_iterator ints_begin() const {return _myints.begin();}
const_iterator ints_end() const {return _myints.end();}
add_IntToMyints(int x){_myints.push_back(x));
};
For good encapsulation, you should keep your vector private.
Your question is not very concrete, so here's an answer in the same spirit:
Generally, your classes should be designed to express a particular concept and functionality. They should not just hand through another member class. If you find yourself replicating all the interface functions of a member object, something is wrong.
Maybe sometimes you really just need a collection of other things. In that case, consider a plain old aggregate, or even a tuple. But if you're designing a proper class, make the interface meaningful to the task at hand, and hide the implementation. So the main question here is, why do you need to expose the vector itself? What is its role in the class? What does its emptiness signify in terms of the semantics of your class?
Find the appropriate idioms and ideas to design a minimal, modular interface for your class, and the question might just go away by itself.
(One more idea: If for example you have some range-based needs, consider exposing a template member function accepting a pair of iterators. That way you leverage the power of generic algorithms without depending on the choice of container.)
Normally, good coding practice is to keep your data members private or protected, and provide whatever public methods will be needed to access them. Not all the methods of (in this case) vector, just what will be useful for your application.
That depends on your class's purpose. If you're trying simply trying to wrap the vector and want to use it as a vector you could make an argument for making the vector public.
Generally speaking I would suggest making it private and providing an appropriate interface to manipulate the container. Additionally this lets you change the container under the hood if a different container would ever be more appropriate (as long as you don't tie your public interface to the container type).
Further as an aside, avoid names that begin with underscores as there are some such identifiers reserved for the implementation and it's safer to just avoid all of them rather than trying to remember the rules in all cases.
A point to realize is that making the std::vector private is only half of the story when it comes to good encapsulation. For example, if you have:
class MyClass {
public:
// Constructors, other member functions, etc.
int getIntAt(int index) const;
private:
std::vector<int> myInts_;
};
...then arguably, this is no better than just making myInts_ public. Either way, clients will write code using MyClass which is dependent on the fact that the underlying representation requires the use of a std::vector. This means that in the future, if you decide that a more efficient implementation would utilize a std::list instead:
class MyClass {
public:
// Constructors, other member functions, etc.
int getIntAt(int index) const; // whoops!
private:
std::list<int> myInts_;
};
...now you have a problem. Since you can't access into a std::list by index, you would either have to get rid of getIntAt, or implement getIntAt using a loop. Neither option is good; in the first case, you now have clients with code that doesn't compile. In the second case, you now have clients with code that just silently became less efficient.
This is the danger of exposing any public member functions which are specific to your choice of implementation. It's important to keep flexibility/future maintenance in mind when designing your class interface. There are a number of ways you could do this with your particular example; see Mooing Duck's answer for one such interface that exposes iterators.
Or, if you would like to maximize code readability, you could design the interface around what MyClass logically represents; in your case, a snake:
class MyClass {
public:
// Constructors, etc.
void addToHead(int value);
void addToTail(int value);
void removeFromHead();
void removeFromTail();
private:
// implementation details which the client shouldn't care about
};
This offers an abstraction of a snake object in your program, and the simplified interface gives you the flexibility to choose whatever implementation suits it best. And if the situation arises, you can always change that implementation without breaking client code.
Theoretically in Object Oriented Programming any attributes should be private and gain access to them via public methods such as Get() and Set().
I think you question is not complete, but what I understand from what you're trying to achieve you need to inherit from std::vector and extend its functionality, to both satisfy your fast access needs and not messing around with encapsulation. (Consider reading on "Inheritance" first from any C++ book, or other OO language)
Having said that, your code might look as following:
class MyClass : public std::vector<int>
{
//whatever else you need goes here
}
int main(void)
{
MyClass var;
var.push_back(3);
int size = var.size(); // size will be 1
}
Hope this answered your question