Study Guide 10 Answers

    Class designers often have a preferred way of orienting the classes and relationship connectors in a UML class diagram. However, constraints such as eliminating or minimizing relationships crossing each other may require us to abandon that orientation, making it necessary to examine the connectors closely to identify a relationship.
  1. b. Alpha is the whole class and Gamma is the part.
  2. c. Beta is the whole class and Delta is the part.
  3. a. Gamma is the superclass and Delta is the subclass.
  4. d. The classes are peers.
  5. e. Delta is the dependent or client class; Epsilon is the independent or supplier class.

  6. Aggregation. Implemented with a class-scope pointer variable.
  7. Composition. Implemented with a class-scope non-pointer variable.
  8. Dependency. A member function has a local variable of class-type. This is a non-standard implementation not recognized by all class developers. However, I believe it is a natural extension of implementing dependency with a function parameter (which is a local variable) and matches my practice as a software engineer. We often omit dependencies from class diagrams because they are numerous and contribute less to our understanding of a system than the other relationships.
  9. Association. Implemented with two class-scope pointer variables, one in each class. Association requires one or two forward references.
  10. Dependency. The accepted implementation of dependency as a member function parameter.
  11. Inheritance. The only relationship implemented with dedicated syntax: : public superclass_name.

  12. Overridden functions
  13. Overloaded functions
  14. Overloaded functions
  15. Overridden functions
  16. b: Sending a message to an object is equivalent to calling one of the object's member functions
  17. a & b: foo has a default constructor, which may be called implicitly (a) or explicitly (b)
  18. a, b, & c: foo has a constructor that requires one integer argument, which is supplied by the initializer lists in the first three choices
  19. d: the foo constructor requires two arguments, and the initializer for (d) is the only one that provides the correct number
  20. a: Although bar inherits function1 from foo, it overrides it with its own version of function1. When looking for inherited features, the compiler will begin with the class named in the variable definition (e.g., bar in bar b) and work its way up the inheritance chain; it will use the first one that it finds (the one in bar in this case).
  21. b: bar inherits function2 from foo and may call it just as if it was defined in foo (remember, a bar is a foo).
  22. c: C++ supports recursion but function1 in bar is not a properly formed recursive function. The body of function1 will call function1, which will call function1, which will. . . . Well, you get the idea.
  23. d: The body of function1 in bar calls function1 in foo. In an inheritance situation like this, the bar function1 is said to be written in terms of the foo function1.
  24. d: Although bar inherits the counter variable from foo, it may not access it directly because it is defined as private in foo. The program will compile and run if private is changed to protected in foo or if foo provided a function to access counter, which would be called in bar.
  25. d: Begin with obj2.print(), you can ignore obj1 because the program doesn't do anything with it after it is constructed. The constructor call for obj2 passes 10 to the constructor, which stores that value in bar my_data. obj2.print() prints the value stored in my_data: 10.
  26. a: When building an initializer list, inheritance must always be initialized before other class relationships; other relationships and variables my initialized in any order.
  27. a: The B initializer is calling the constructor function in A, and the number of arguments in the call must match the number of parameters in the function definition
  28. c: Use the member variable name in whole class to call a constructor in the composed or part class
  29. my_bar(a, b)
  30. my_bar.display()
  31. my_bar->display()
  32. b: foo doesn't have any pointer members, so it doesn't need a copy constructor
  33. bar::bar(bar& a_bar)
    {
    	name = new char[strlen(name) + 1];
    	strcpy(name, a_bar.name);
    	salary = a_bar.salary;
    }
  34. The two classes are related by inheritance
    1. count(a_count), balance(a_balance) -- order is not significant
    2. Bar(count, balance), name(a_name) -- Bar must be first
    3. Bar::display()
  35. The two classes are related by composition
    1. count(c), balance(b) -- order is not significant
    2. my_bar(c, b), name(n) -- order is not significant
    3. my_bar.display()
  36. The two classes are related by aggregation
    1. count(c), balance(b)
    2. name(n), my_bar(nullptr) -- the highlighted code is optional but was required in older versions of C++
    3. if (my_bar != nullptr) delete my_bar
    4. if (my_bar != nullptr) delete my_bar
    5. my_bar = new Bar(c, b)
    6. if (my_bar != null_nullptr) my_bar->display()
  37. There are several unique inheritance characteristics, and describing of any one of them satisfies the question.
  38. Association is the only bidirectional or two-way relationship. Like aggregation and composition, it is a "Has-A" relationship, but unlike them, it reads well in both directions.
  39. As suggested by the similarity of their respective UML connector symbols, aggregation and composition have much in common. Both form a one-way or unidirectional or "Has-A" connection, implementing a whole-part relationship. However, they differ in their respective binding strengths (i.e., the "tightness" of their bindings). Binding strength summarizes the related object's relative lifetimes and the ability of the whole to share its parts. Composition's strong or tight binding requires the whole and part to have simultaneous (i.e., the same) lifetimes - the program creates and destroys the whole and part at the same time. Aggregation's weak or loose binding allows the the objects to have independent or different lifetimes - the program can create or change the connection between the whole and part whenever doing so is convenient. Composition doesn't allow a whole to share its part, while aggregation allows sharing.