From: Francis Glassborow on 10 Dec 2009 03:59 Kaz Kylheku wrote: > On 2009-12-09, Francis Glassborow <francis.glassborow(a)btinternet.com> wrote: >> The fact remains that with or without your approval, those being taught >> C++ from scratch are taught (correctly IMNSHO) to make their data >> members private. > > Newbies being taught correctly are taught to make /everything/ private > that doesn't need to be, including most member functions. Not only > data members. > > Your argument boils down to that things which are invoked without parentheses > are evil and should be made public, but whereas invoked with parentheses can be > made public. Do not try to put words into my mouth. > > If an object is understood to be a rectangular coordinate, and it has members > which are private, but there exist the public functions get_x() and get_y(), > then it actually does not truly have private members. These functions > almost directly expose the semantics of the object: that it has x and y > coordinates. Just because a class has a get_x() does not mean that there is actually an x data member, all it means is that the public interface supports the users need for an x value. In the case of point co-ordinate representation, in 2D we have two equally valid representations, Cartesian and Polar. There is no need for the user to know which is being used internally. > > If the users of a coordinate class depend on the accessors get_x() and get_y(), > and if the users depend on the data members x and y, it is the same. In either > case, we have a dependency of the client code on a representational artifact of > the coordinate, which we cannot revoke without rewriting all of the client > code. Completely false and that blind spot shows up the problem with your thinking. In either case, we can still retarget and virtualize that class to use a > non-rectangular representation of the coordinate: we can make the data member > actually behave as an abstract accessor. > > This can be done with existing features of C++. > > At one point, it was the subject of a C++0x proposal: ``implicitly callable > functions''. > > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1611.pdf > > How we can do this today is in various ways. E.g. > > class myclass { > private: > void set_x(int); > int get_x(); > public: > accessor<myclass, int> x; > myclass(); > } > > myclass::myclass() > : x(this, &myclass::set_x, &myclass::get_x) > { > } > > Exercise for reader: implement accessor<>. The member x has to have an > assignment operator void operator =(int) which passes the value to > set_x, and a conversion operator from int which works by calling > get_x, and of course the constructor. All that complexity to save some parentheses:) And when you want to change the internals from Cartesian to Polar all that extra work. > > One nice thing is that we can even indirect upon x independently of the object > that it came from: > > accessor<myclass, int> &a = obj.x; > > a = 42; // calls obj.set_x(42) > > You could teach newbies how to use all this, the same way that > you can teach newbies cout << foo << endl . Maybe I could but I am certain that I would not.
From: Pat on 10 Dec 2009 09:16 Francis Glassborow wrote: > You seem to have got hooked on the idea that a struct and a class are > different in some important way, they aren't. The important thing is to > keep internal data internal and that is the concept of private access. > Apart from convention, you could just as well write the above as: > > struct Point { > public: > Point(double x = 0.0, double y = 0.0); > double x(); > double y(); > private: > double x_; > double y_; > }; > Indeed if you did that you could omit the first access specifier (the > 'public:') but others would find your style non-idiomatic. The value of > idioms is that it makes it easier for others to understand you. Yes, your right. In my mind I was viewing structures and classes as different things. I've been teaching myself C++ with the help of several books. In the text that has served as my primary reference, structures were introduced fairly early (well ahead of classes). So I got use to using those well before knowing what a class was. I have to say, C++ is the most complex programming language I have ever learned. Its taken a while to digest it all (or least the little bit I've learned). This newsgroup has been a big help though, and I appreciate all the responses I've gotten to my questions. Pat
From: Kaz Kylheku on 10 Dec 2009 15:42 On 2009-12-10, Francis Glassborow <francis.glassborow(a)btinternet.com> wrote: > Kaz Kylheku wrote: >> On 2009-12-09, Francis Glassborow <francis.glassborow(a)btinternet.com> wrote: >>> The fact remains that with or without your approval, those being taught >>> C++ from scratch are taught (correctly IMNSHO) to make their data >>> members private. >> >> Newbies being taught correctly are taught to make /everything/ private >> that doesn't need to be, including most member functions. Not only >> data members. >> >> Your argument boils down to that things which are invoked without parentheses >> are evil and should be made public, but whereas invoked with parentheses can be >> made public. > Do not try to put words into my mouth. >> >> If an object is understood to be a rectangular coordinate, and it has members >> which are private, but there exist the public functions get_x() and get_y(), >> then it actually does not truly have private members. These functions >> almost directly expose the semantics of the object: that it has x and y >> coordinates. > > Just because a class has a get_x() does not mean that there is actually > an x data member, all it means is that the public interface supports the > users need for an x value. In the case of point co-ordinate > representation, in 2D we have two equally valid representations, > Cartesian and Polar. There is no need for the user to know which is > being used internally. Ah, I almost understand. Maybe if you could repeat that just one more time, it would sink in. Yes, I think the reason I disagree with you is that I don't understand this whole polar and rectangular thing. That's what it must be. So one more time: we have an object which looks like a Cartesian coordinate, but in fact, it clumsily emulates one on the fly by converting to and from an internal polar representation. Does stupid me finally have it right? Ah, now I think I see it. Of course, for proper abstraction, you must have public functions get_x and get_y, and not abstract accessors x and y which look like public data members, but actually call functions. If we have such abstract accessors, then the object really /is/ a Cartesian coordinate, because it looks too much like one. The parentheses in the function calls tell the users of the class that it's not really a Certesian cooredinate. If you pull out the x coordinate with coord.x(), you are not actually relying on the fact that the object has an x coordinate. The parentheses make this nice and virtual. But if you retrieve it it out with just coord.x, then, oh boy, you /are/ relying on this fact; your code is now hopelessly coupled to the concept that the object is a Cartesian coordinate pair, unlike the nice code which calls coord.x(), even if this coord.x is a special data member that calls a member function to compute the value. Moreover, we must not use C++ to its potential with ugly things like abstract_accessor<class, type> x; Anything missing?
From: Alf P. Steinbach on 10 Dec 2009 17:36 * Kaz Kylheku: > On 2009-12-10, Francis Glassborow <francis.glassborow(a)btinternet.com> wrote: >> Kaz Kylheku wrote: >>> On 2009-12-09, Francis Glassborow <francis.glassborow(a)btinternet.com> wrote: >>>> The fact remains that with or without your approval, those being taught >>>> C++ from scratch are taught (correctly IMNSHO) to make their data >>>> members private. >>> Newbies being taught correctly are taught to make /everything/ private >>> that doesn't need to be, including most member functions. Not only >>> data members. >>> >>> Your argument boils down to that things which are invoked without parentheses >>> are evil and should be made public, but whereas invoked with parentheses can be >>> made public. >> Do not try to put words into my mouth. >>> If an object is understood to be a rectangular coordinate, and it has members >>> which are private, but there exist the public functions get_x() and get_y(), >>> then it actually does not truly have private members. These functions >>> almost directly expose the semantics of the object: that it has x and y >>> coordinates. >> Just because a class has a get_x() does not mean that there is actually >> an x data member, all it means is that the public interface supports the >> users need for an x value. In the case of point co-ordinate >> representation, in 2D we have two equally valid representations, >> Cartesian and Polar. There is no need for the user to know which is >> being used internally. > > Ah, I almost understand. Maybe if you could repeat that just one more time, > it would sink in. > > Yes, I think the reason I disagree with you is that I don't understand > this whole polar and rectangular thing. That's what it must be. > > So one more time: we have an object which looks like a Cartesian coordinate, > but in fact, it clumsily emulates one on the fly by converting to and from an > internal polar representation. Does stupid me finally have it right? > > Ah, now I think I see it. Of course, for proper abstraction, you must have > public functions get_x and get_y, and not abstract accessors x and y which look > like public data members, but actually call functions. > > If we have such abstract accessors, then the object really /is/ a > Cartesian coordinate, because it looks too much like one. > The parentheses in the function calls tell the users of the > class that it's not really a Certesian cooredinate. > > If you pull out the x coordinate with coord.x(), you are not actually > relying on the fact that the object has an x coordinate. The parentheses > make this nice and virtual. But if you retrieve it it out with just coord.x, > then, oh boy, you /are/ relying on this fact; your code is now hopelessly > coupled to the concept that the object is a Cartesian coordinate pair, unlike > the nice code which calls coord.x(), even if this coord.x is a special > data member that calls a member function to compute the value. > > Moreover, we must not use C++ to its potential with ugly things like > > abstract_accessor<class, type> x; > > Anything missing? Well I don't think it's a good idea to get into a flame war with Francis. I think Francis simply hasn't realized that you're thinking of moving encapsulation down from the class level to individual data members. It's very easy to not consider that because it has so severe costs that nobody who is able to converse intelligently about C++ (as you do) does it: * Each such silly beast needs back-pointer to containing object for the general case (and this means that it will probably have a back-pointer regardless, forced by an abstraction such as your 'abstract_accessor'). More space, more time. * The member's type A<T> is not directly the design level type T. This trips you up in e.g. IDE, in calls to printf (you have to cast), so on. I imagine that it will be especially bad when interacting with templated code. * The usual access machinery doesn't apply, so for the general case you need abstract_accessor to be 'friend'. Cheers & hth., - Alf
From: Francis Glassborow on 11 Dec 2009 08:28
Pat wrote: > > Yes, your right. In my mind I was viewing structures and classes as > different things. I've been teaching myself C++ with the help of > several books. In the text that has served as my primary reference, > structures were introduced fairly early (well ahead of classes). So I > got use to using those well before knowing what a class was. So what was the primary textbook? Because introducing structs like that seems unhelpful (but typical of authors who think you should learn the C way before unlearning it to learn the C++ way :) } > > I have to say, C++ is the most complex programming language I have ever > learned. Its taken a while to digest it all (or least the little bit > I've learned). This newsgroup has been a big help though, and I > appreciate all the responses I've gotten to my questions. Yes C++ is a very complex language but like English using it does not require mastery of all or even most of it. |