Jump to content

  • Log In with Google      Sign In   
  • Create Account


oop question


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
21 replies to this topic

#1 phil67rpg   Members   -  Reputation: 767

Like
0Likes
Like

Posted 27 October 2013 - 10:23 PM

when do you use the public and private data members.



Sponsor:

#2 exOfde   Members   -  Reputation: 809

Like
1Likes
Like

Posted 27 October 2013 - 10:44 PM

private data-members are used if you want hide those data members from other classes or the user himself.
public members are used if you "don't care" what happens to your member.
easy said...
but it's possible to explain it more specific

#3 N.I.B.   Members   -  Reputation: 1165

Like
1Likes
Like

Posted 27 October 2013 - 10:57 PM

My rule of thumb is this:

I use classes whenever I have logic to manipulate my data members. Then all the data members are private, and I have setters/getters for them. For example, CVertexShader() - it has logic for creating, destroying, setting a vertex shader, and I don't expose any of it's internals. This allows better abstraction, and if I ever need to change something with vertex shaders, it keeps the changes localized.

 

For data containers I use structs and makes everything public. Basically, stuff that I don't need to manipulate, just store and retrieve data. In that case setters/getters are just a hassle. If at any point this data starts to have logic - I convert it into a class.

 

Putting it all together - my constants buffer objects are classes with private data members, but the CBs data containers are structs. This allows my UI thread to easily change the CBs data, while hiding all the API logic inside a class.



#4 Krohm   Crossbones+   -  Reputation: 3049

Like
3Likes
Like

Posted 28 October 2013 - 01:55 AM

Formally, each class has an implicit property called class invariant. It's the assumption you can always make about each object instantiated using that class.

In practice, we must ensure each object is valid - invariant is satisfied - and you can guarantee this only by taking each modification attempt and verify it transitions your object to another valid state.

Of course, you cannot do that on stuff that is directly assignable. So, as above, public members are "don't care".

In line of concept, you should use private on all other cases. But in reality protected is often a good compromise, due to specificity of derived class code - if someone is writing a derived class, he has to deal with much more focused context than the whole program. Someone think protected is bad and to a certain degree I agree with them but in the real world, I find it very convenient.

 

Edit: derided class code... what a typo!


Edited by Krohm, 28 October 2013 - 07:23 AM.


#5 wintertime   Members   -  Reputation: 1644

Like
0Likes
Like

Posted 28 October 2013 - 02:11 AM

Theoretically everything outside a class shouldn't need to know about its data, thats why they are private by default. Using public is like exposing the innards of the class to the whole world.

If following "tell, don't ask" principle you would also just call a method to tell an object what to do; not use a getter to inspect it, do some outside decision and use a setter to change it from outside.


Edited by wintertime, 28 October 2013 - 02:11 AM.


#6 GearTreeEntertainment   Members   -  Reputation: 323

Like
0Likes
Like

Posted 28 October 2013 - 05:28 AM

You want to make variables in classes private, ALL the time. But what you want to do is make an Accessor Function, or a "getter". This will allow you to obtain the variable even if it is private. But make sure you make the functions public, so you will be able to access them. You can also use a setter function, this will allow you to set the value of the private variable, but it is a public function, so you will be able to access it.


Edited by GearTreeEntertaiment, 28 October 2013 - 05:30 AM.


#7 Paradigm Shifter   Crossbones+   -  Reputation: 5255

Like
4Likes
Like

Posted 28 October 2013 - 05:35 AM

I don't agree.

 

If there are no invariants to worry about, and the implementation is simple and obvious (i.e setting a variable and doing no verification of validity), making something public is fine.

 

I wouldn't have setX, getX, etc. for a 3D vector class, since all values are valid.

 

If there was any reason to limit the bounds of a 3D vector (e.g. physics constraints on world size), then the implementation is no longer simple and obvious so then get/set methods would be appropriate.

 

All pointer members should be private though.


Edited by Paradigm Shifter, 28 October 2013 - 05:40 AM.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#8 Radikalizm   Crossbones+   -  Reputation: 2825

Like
0Likes
Like

Posted 28 October 2013 - 06:08 AM


I wouldn't have setX, getX, etc. for a 3D vector class, since all values are valid.

 

Not to be nitpicky here, but what about values like NaN or infinity? NaN could definitely break the conditions for satisfying the class invariant for a vector class

It's all about design of course; I don't use mutators and accessors in my vector classes either since you should be able to avoid cases like NaN quite easily by just using common sense


I gets all your texture budgets!


#9 Paradigm Shifter   Crossbones+   -  Reputation: 5255

Like
0Likes
Like

Posted 28 October 2013 - 06:14 AM

That's handled by the floating point specification, and adding checks is going to affect performance.

 

You could put debug only checks in, then you would use an accessor and inline it. I wouldn't do that for a vector class though. I have used it for things like verifying arguments are within expected ranges e.g. for inverse trig functions.


"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#10 jbadams   Senior Staff   -  Reputation: 17989

Like
1Likes
Like

Posted 28 October 2013 - 06:14 AM

You want to make variables in classes private, ALL the time. But what you want to do is make an Accessor Function, or a "getter". This will allow you to obtain the variable even if it is private. But make sure you make the functions public, so you will be able to access them. You can also use a setter function, this will allow you to set the value of the private variable, but it is a public function, so you will be able to access it.

Don't just blindly make every class member private with an accessor; sometimes there should be no accessor, and sometimes public access makes more sense. The sensible thing to do is actually consider the invariants and intended usage of your class and make members private and/or provide accessors when it's genuinely the most appropriate design.

Plain setters are sometimes valuable, but not always the best idea; it often makes more sense to provide a semantically relevant function that might adjust multiple values rather than a simple setter - for example, rather than providing setters for x and y values you might provide a single move() function that sets (and perhaps validates) both values.

#11 Paradigm Shifter   Crossbones+   -  Reputation: 5255

Like
0Likes
Like

Posted 28 October 2013 - 06:25 AM

Agreed. A class should represent an interface rather than thinking in terms of their data members (which clients should not need to even know about).

 

In the vector 3D case though, the representation IS the interface.

 

You would use accessors for simple and obvious access functions if you think there may be a need for them later on though. (I've seen arguments saying it is easier to do a text search for an accessor rather than a member, however I dismiss that since you can comment out the member and the compile errors tell you where the member is used).


"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#12 Radikalizm   Crossbones+   -  Reputation: 2825

Like
0Likes
Like

Posted 28 October 2013 - 06:27 AM

That's handled by the floating point specification, and adding checks is going to affect performance.

 

You could put debug only checks in, then you would use an accessor and inline it. I wouldn't do that for a vector class though. I have used it for things like verifying arguments are within expected ranges e.g. for inverse trig functions.

 

Again, not to be difficult here since I agree with your opinion on the subject completely, but if you want to look at it formally wasn't the concept of class invariants introduced to avoid cases where you can get unexpected or undefined behaviour? I'd assume that some floating point specifications would show undefined behaviour when doing operations on NaN values which would be an issue if you want to be really strict about your OO design.

 

And yes, checks would affect performance, but there will always be a difference between writing code which can be proven to be correct and writing highly performant code.


I gets all your texture budgets!


#13 Paradigm Shifter   Crossbones+   -  Reputation: 5255

Like
0Likes
Like

Posted 28 October 2013 - 06:36 AM

Floating point specs are perfectly well defined for operations involving NaNs and infinities. It wouldn't be much of a specification if they weren't! (Basically once you get to NaN or infinity values there is no going back to "real numbers").

 

For non-conforming implementations you need to check the compiler documentation (non conforming stuff usually only affects things like rounding modes and precision rather than behaviour of NaN and infinities though). If conformance is required you can usually enable it (and take a performance hit).


"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#14 N.I.B.   Members   -  Reputation: 1165

Like
0Likes
Like

Posted 28 October 2013 - 06:38 AM


there will always be a difference between writing code which can be proven to be correct and writing highly performant code

I disagree. Highly performant code can and should be correct. Always.



#15 SimonForsman   Crossbones+   -  Reputation: 6059

Like
0Likes
Like

Posted 28 October 2013 - 08:22 AM

 


there will always be a difference between writing code which can be proven to be correct and writing highly performant code

I disagree. Highly performant code can and should be correct. Always.

 

 

There is a very big difference between "The code should be correct" and "The code is proven to be correct".

In the second case it is impossible for a bug to exist in the code, in the first case testing hasn't discovered any bugs (yet).


Edited by SimonForsman, 28 October 2013 - 08:28 AM.

I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

#16 N.I.B.   Members   -  Reputation: 1165

Like
0Likes
Like

Posted 28 October 2013 - 08:44 AM


There is a very big difference between "The code should be correct" and "The code is proven to be correct".

In the second case it is impossible for a bug to exist in the code, in the first case testing hasn't discovered any bugs (yet).

I don't see why performance has any bearings on it. If you can write crappy-debug code that is proven to be correct, and you know how to optimize, then you can write highly efficient and optimized code that is proven to be correct.



#17 Radikalizm   Crossbones+   -  Reputation: 2825

Like
0Likes
Like

Posted 28 October 2013 - 11:01 AM

 


There is a very big difference between "The code should be correct" and "The code is proven to be correct".

In the second case it is impossible for a bug to exist in the code, in the first case testing hasn't discovered any bugs (yet).

I don't see why performance has any bearings on it. If you can write crappy-debug code that is proven to be correct, and you know how to optimize, then you can write highly efficient and optimized code that is proven to be correct.

 

 

Debugged code is not code which has been proven to be correct.

We're talking about a formal proof here, and formally proving that an algorithm or procedure is correct (ie. it generates a correct output for each input) is not a trivial task. You can debug the crap out of a piece of code, but if you haven't shown that this piece of code provides a correct output for every possible input then you haven't proven this code to be correct.

 

These kinds of proofs are very important when doing design by contract for example. In critical applications it's an absolute must that you have a guarantee that your code will behave correctly in any situation.


I gets all your texture budgets!


#18 N.I.B.   Members   -  Reputation: 1165

Like
0Likes
Like

Posted 28 October 2013 - 11:37 AM

I understand, and I agree that it is not a trivial task, especially if you need high performance.

It doesn't mean you can't write high performance code that is always correct.

#19 Radikalizm   Crossbones+   -  Reputation: 2825

Like
0Likes
Like

Posted 28 October 2013 - 12:37 PM

I understand, and I agree that it is not a trivial task, especially if you need high performance.

It doesn't mean you can't write high performance code that is always correct.

 

I was writing up a huge wall of text, but decided it wasn't worth it in the end.

 

Let me explain what I meant with my original statement:

 

The point I'm trying to make is that high performance is often paired together with designing with the hardware in mind, not the programmers.

You'll often be skipping over some checks (ie. invariant enforcements) or exposing some internal state to gain a performance boost while making the assumption that anyone using the code will be "smart" enough not to provide nonsense input values. This in turn will make it impossible to prove your code to be correct since you can't guarantee you'll conform to your class invariant at all times.


I gets all your texture budgets!


#20 N.I.B.   Members   -  Reputation: 1165

Like
0Likes
Like

Posted 28 October 2013 - 12:48 PM

OK, I thought you were suggesting it's an impossible task.

You'll often be skipping over some checks (ie. invariant enforcements) or exposing some internal state to gain a performance boost

Yep, I agree.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS