16.5 — Dependencies

So far, we’ve explored 3 types of relationships: composition, aggregation, and association. We’ve saved the simplest one for last: dependencies.

In casual conversation, we use the term dependency to indicate that an object is reliant upon another object for a given task. For example, if you break your foot, you are dependent on crutches to get around (but not otherwise). Flowers are dependent upon bees to pollinate them, in order to grow fruit or propagate (but not otherwise).

A dependency occurs when one object invokes another object’s functionality in order to accomplish some specific task. This is a weaker relationship than an association, but still, any change to object being depended upon may break functionality in the (dependent) caller. A dependency is always a unidirectional relationship.

A good example of a dependency that you’ve already seen many times is std::cout (of type std::ostream). Our classes that use std::cout use it in order to accomplish the task of printing something to the console, but not otherwise.

For example:

In the above code, Point isn’t directly related to std::cout, but it has a dependency on std::cout since operator<< uses std::cout to print the Point to the console.

Dependencies vs Association in C++

There’s typically some confusion about what differentiates a dependency from an association.

In C++, associations are a relationship between two classes at the class level. That is, one class keeps a direct or indirect “link” to the associated class as a member. For example, a Doctor class has an array of pointers to its Patients as a member. You can always ask the Doctor who its patients are. The Driver class holds the id of the Car the driver object owns as an integer member. The Driver always knows what Car is associated with it.

Dependencies typically are not represented at the class level -- that is, the object being depended on is not linked as a member. Rather, the object being depended on is typically instantiated as needed (like opening a file to write data to), or passed into a function as a parameter (like std::ostream in the overloaded operator<< above).

Humor break

Dependencies (courtesy of our friends at xkcd):

Of course, you and I know that this is actually a reflexive association!

16.6 -- Container classes
16.4 -- Association

20 comments to 16.5 — Dependencies

  • Leo Alexander A

    There is a class object A which is not compatible with class B object. But to make A and B object compatible,
    there is a dependency with class C (Adapter) object.

  • Tim

    >>but still, any change to object being depended upon may break functionality in the (dependent) caller.
    Can you give me an example of the statement above in the class Point?

  • in the section: "Dependencies vs Association in C++"
    Since the dependent is the caller, I'am not sure but should it be "object we depend on" instead "dependent object" ?

  • stannis

    "A dependency is always a unidirectional relationship."
    Why can't you have bidirectional dependency?
    Eg. If a flower depends on bees to pollinate and bees depend on flower to feed, is this not bidirectional dependency?

    • Alex

      C++ can't easily represent bidirectional dependencies, so in such a case we'd model this as mutual dependencies (flower has a dependency on bee, and bee has a dependency on flower).

  • Benjamin


    Probably this is more a question about English language (which is not my mother tongue) than C++, but I was surprised when you wrote "any change to the dependent object may break functionality in the caller". Is not the caller the dependent one, as he depends on the functionality of the called object, which is used in the dependency-relationship?

    In the example with the flowers and the bees (hehe), you actually call the flower the dependent one. This agrees with my understanding. The two statements are not contradicting in their use of "dependent"?

    PS.: Little typo: the last sentence "Of course, you and I know that this actually a reflexive association!" misses an "is".

    • Alex

      You are correct, I did not write what I had intended. The intention was to note that a change to the object being depended upon could break the class with the dependency. I've updated the text, as well as corrected the typo.



    I have been reading this far, but I still don't get otherwise unrelated and not otherwise mean.

    • Alex

      "but not otherwise" means "but not in situations where the preceding statement isn't true". For example, if I say I like eggs on Sunday but not otherwise, that means I only like eggs on Sunday and not on other days of the week.

  • Simon

    Alex I feel these relations are really important for finding better solutions for real life problems and I'm really interested in them. What is a good book you might want to suggest for reading about them in more depth?

    • Alex

      I don't have any good books in mind for this -- I scraped these together from various sources on the web. You might try doing some reading on UML modelling.

  • ali

    hello Alex I am a newly graduated student when I was in college we have something about DBMS (database management system) the thing is we studied the relationships between entities like (the department has one manager, the company has several departments) and did some kind of query using SQL the quistion: is the relationships in SQL are implemented just like you explained? if not could we do like them in c++ techniques

    • Alex

      Yes, these relationships are applicable to databases. Databases are often described using UML, and UML contains symbols to model these different relationship types.

      I don't talk about UML here specifically, because it's not directly related to C++, but a lot of the material in this chapter maps to topics that are often discussed in UML.

  • daniel

    Thank you for this great tutorial.
    I found one typo: There should be a verb "IS" in the last sentence.

    Of course, you and I know that this "IS" actually a reflexive association!

  • Matt

    Typo in section "Dependencies vs Association in C++"... second paragraph, second sentence. I think "a a" should be "as a".

  • daniel

    when you say

    outside of the class and don't mention Point::std::ostream, how does compiler know its the operator overload for point class.
    what if there is more than one class and both have this kind of overload ?

    • Alex

      There is no such thing as Point::std::ostream. I'll presume you meant Point::operator<<. What happens is when you do something like this:

      C++ tries to match this to a function. It'll try to see if there is a std::ostream::operator<<(Point) function, but there obviously won't be. Next it checks for an operator<<(std::ostream, Point). It will find our overloaded operator definition and match to that. Note that in a binary operator, the left hand side operand always becomes the implicit object, so there's never any ambiguity about which class to look in. For non-member functions, the left hand side operand becomes the first parameter and the right hand side operator becomes the second, so there's also no ambiguity here.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]