Sorry~~, I don't know where to post this quetion.

Can someboy help me with this question, plz....

Suppose someone designed a stack abstract data type in which the top function returned an access path (or pointer), rather than returning a copy of the top element. This is not true data abstraction. Why?

>This is not true data abstraction.
Sure it is. The abstraction is the stack and its implementation, not the contents of the stack. Returning a copy of the top of the stack instead of a pointer to it makes no difference in how the stack works. Presumably the question is assuming that a malicious coder can break umpteen language rules to get a hold of other items if given a pointer to one item, but that's equally likely with nothing more than a stack object regardless of how much abstraction you put into it.

It's certainly poor encapsulation.

Giving someone a pointer to the innards of your class exposes you to all sorts of problems. What if they try to write to your class data via the pointer? What if they increment the pointer, where does it point to then?
Applying all sorts of const to the result can only go so far.

Yes, std::string has the c_str() method which returns a pointer to something on the inside, but that's more a "necessary evil" rather than an example of good design IMO.

very often, encapsulation/insulation and efficiency pull in opposite directions. and c++ programmers have to do a fine balancing act between the two and decide what is most appropriate in a particular case. for example,

struct book // fully insulated, least efficient
{
  book( const atring& t, const list<string>& a, const string& n ) ;
  book( const book& ) ;
  book& operator=( const book& ) ;
  ~book() ;
  string title() const ;
  list<string> authors() const ;
  string isbn() const ;
  // ...
  private:
    struct implementation ;
    implementation* opaque_pointer ;
};
struct book // encapsulated, partially insulated
            // more efficient 
{
  book( const atring& t, const list<string>& a, const string& n ) ;
  book( const book& ) ;
  book& operator=( const book& ) ;
  ~book() ;
  string title() const ;
  list<string> authors() const ;
  string isbn() const ;
  // ...
  private:
    string _title ;
    list<string> _authors ;
    string _isbn ;
    // ...
};
struct book // encapsulated, not insulated
            // even more efficient (inlining)
{
  book( const atring& t, const list<string>& a, const string& n ) ;
    : _title(t), _authors(a), _isbn(n) { /* ... */ }
  string title() const { return _title ; }
  list<string> authors() const { return _authors ; }
  string isbn() const { return _isbn ; }
  // ...
  private:
    string _title ;
    list<string> _authors ;
    string _isbn ;
    // ...
};
struct book // less encapsulated, not insulated
            // most efficient (no copy of objects)
{
  book( const atring& t, const list<string>& a, const string& n )
    : _title(t), _authors(a), _isbn(n) { /* ... */ }
  const string& title() const { return _title ; }
  const list<string>& authors() const { return _authors ; }
  const string& isbn() const { return _isbn ; }
  // ...
  private:
    string _title ;
    list<string> _authors ;
    string _isbn ;
    // ...
};

;

This article has been dead for over six months. Start a new discussion instead.