Transcript Document

C++ Certificate Program
C++ Intermediate
Access Control
©Fraser Hutchinson & Cliff Green
What is Access Control?
• Three tenets of O-O programming:
– Encapsulation
– Inheritance
– Polymorphism (typically runtime / dynamic binding)
• Access control concerned with encapsulation
– What do we want visible?
– What do we want to hide?
– From whom?
©Fraser Hutchinson & Cliff Green
C++ Access Control
• C++ supports three levels of access control
– Public : visible to all
– Protected: visible to derived classes
– Private: visible only to the class
©Fraser Hutchinson & Cliff Green
Access Control Uses
• Intended to support design policy
– Aids in the communication of a design by
delineating what is intended to be visible
– Can be used to promote loose-coupling (hard to
couple to what you cannot see)
• C++ access control is not a runtime security
mechanism, but a compile-time design
enforcement mechanism
©Fraser Hutchinson & Cliff Green
Sibling Access
class Car {
protected:
double getMilesPerGallon () const { /* … */ }
// …
};
namespace Honda {
class Civic : public Car {
public:
double getResaleValue () const {
double mpg = getMilesPerGallon (); // ok
// …
}
bool shouldTradeFor (Car const& car) {
double newMPG = car.getMilesPerGallon (); // ILLEGAL!
// …
}
};
}
©Fraser Hutchinson & Cliff Green
Sibling Access
• Why is this illegal?
– Protected and private methods can be accessed
between different objects of the same class
– Base class protected method can be called from
within derived object method
– However, siblings should not have access to the
other’s private (or protected) methods; for
example, Civic should not be able to call
getMilesPerGallon on a Saab object
©Fraser Hutchinson & Cliff Green
Explanation from ARM
• The C++ Annotated Reference Manual (ARM)
explains this further:
– When a friend or a member function of a derived class
references a protected nonstatic member of a base class,
an access check applies in addition to those described
earlier. . . Except when forming a pointer to member,
the access must be through a pointer to, reference to, or
object of the derived class itself (or any class derived
from that class). . .
©Fraser Hutchinson & Cliff Green
Friend Declarations
• A class, global function, or method may be
declared to be a friend of a class
• Friend has unrestricted access to private and
protected members of the class
• Friend declarations are not inherited or transitive a friend of a friend does not automatically become
a friend, a friend of a parent does not
automatically become a friend
©Fraser Hutchinson & Cliff Green
Example Friend Declarations
class Employee {
// friend functions and classes are
// given unrestricted access to all
// public, private and protected
// attributes and methods
friend class Secretary;
friend void ::IRS_Audit();
friend void Boss::Spy();
};
©Fraser Hutchinson & Cliff Green
More on Friends
• You can specify who your friends are
• You cannot limit what friends have access
to
– Friends can access everything an instance of
your class can
• Often, but not always, use of friends is
indicative of a weak design
©Fraser Hutchinson & Cliff Green
Template Friends
• Friends can be declared in template classes,
to generate many friends:
template <typename T>
class Bar { };
template <typename T>
class Foo {
// ...
friend class Bar<T>;
};
©Fraser Hutchinson & Cliff Green
Iterators
• Iterator classes provide ideal example where
friend relationships can actually produce better
design
• Iterators require intimate knowledge of the
container class it is iterating against
• A container typically needs one outside class
(usually under control of the container designer)
with intimate knowledge of the container
implementation details; outside users need only
know container interface details
©Fraser Hutchinson & Cliff Green
Std Lib List Container
• In the example of std::list, every user
of the class accesses the list through its non
data-revealing / non implementationrevealing public interface
• Iterator is needed to access any elements
©Fraser Hutchinson & Cliff Green
Iterator Design Drivers
Why are the iterator classes separate, nested classes rather
than just exposing data within the list's interface?
• Is one iterator enough? Will there be multiple clients to the
container?
– Multiple iterators are needed
• Will standard algorithms be used on the container?
– Iterators allow generic algorithms that work with any
container
– Algorithm code is insulated from binding to members
of any specific container
©Fraser Hutchinson & Cliff Green
Iterator Design Drivers
• Will there ever be a need to change the underlying
container?
– Iterators reduce reliance on a specific class interface
– Underlying container can be changed and the
application code is unaffected
©Fraser Hutchinson & Cliff Green
Iterators Are Your Friends
• All of the above pushes for the use of iterators
– “a window into a container”
– Client code still has control over the container, regardless of what
really goes on behind the scenes
• Iterators are an excellent example of selective exposure
– Clients get what they need and only what they need
– Many functions only need to access container iterators, not the
container itself
– Decouples client code from the implementation of the containers
©Fraser Hutchinson & Cliff Green
Summary
• C++ access control and friends are all aspects of
the public interface
• Public interface defines what a type can do, to the
users of that type
• Separating the interface from the implementation
is crucial to good software design
• The responsibilities / functionality / interface of a
type (class) lies at the heart of O-O programming
©Fraser Hutchinson & Cliff Green