2

I'm a bit confused so the question is a bit confusing. TL;dr: how to mix STL and OOP?

From the comment to Best overview to modern C++ paradigms? and http://www.boost.org/community/generic_programming.html there isn't much about objects-oriented programming. (boost guidelines mention object generators).

When planing a program, it seems that STL and objects should fit well together. You think of an algorithm and how to do things, then you think of what are the things you want to work with and what properties/characteristics they have. You express those things in terms of tuples and containers and you apply algorithms to them. From my understanding, that's STL style of thinking.

Now this is where objects come in. They are things that you do stuff with that contain data, algorithms that change that data and interfaces. But that overlaps with idea of stl where you separate data and algorithms.

In OO you combine data and algorithms and in STL you separate it.

Although mathematically and generically STL make more sense (when you can apply the algorithm to anything), it is easier to think conceptually in OO style when you have a lot of different objects and algorithms -- you get a better organization. For example, qt-style advocates using minimal and orthogonal interfaces specific to a class as oppose to general algorithms. I said specific because their objects are different and they ask for minimal interfaces meaning objects won't share the same interfaces.

So the question is: "can you get away with STL in modern C++ or should you use objects? and if you have to use objects then how?"

Other relevant questions at Stack Overflow:

2
  • 4
    Your question is based on a false premise, which is that objects containing only data or only code are not, by definition, object-oriented, which is not true. The combining of code and data together in the same object is only one aspect of object-orientation, and even the most staunch advocates of OO sometimes separate their code and their data. Commented Mar 21, 2013 at 22:16
  • 1
    i was coming from the definition on wikipedia en.wikipedia.org/wiki/Object-oriented_programming -- objects are data and associated methods. i'm asking about fundamental guidelines of paradigms rather then specialized cases that not all practitioners use. Commented Mar 21, 2013 at 22:28

2 Answers 2

3

One thing that you should be careful to not forget is that C++ is a multi-paradigm language. It is a language that supports abstractions from low-level imperative code up to high-order functional code, and almost everything in between.

The standard containers (not the STL - that's a mostly unrelated library) are a type of abstraction that sits closer to the functional part of the paradigm spectrum. It provides the most generic interface possible to a category of standard algorithms, in a form that follows a functional style - a style in which algorithms and data structures are described in very high-level but consistent terms.

This is not at odds with the object-oriented paradigm that you are likely accustomed to. Rather, it is both orthogonal and complementary.

The reason modern C++ discussions don't revolve much around object-orientation is simply due to the fact that objects are merely one of the many tools C++ offers to model the computations that underlie user-defined types.

To restate that another way: The focus in modern C++ is in types. Objects happen to be used to model the behavior of some types, and templates and functions model the behavior of other types.

This is not the "STL way of thinking," rather, it is a paradigm that takes full advantage of the functional paradigm in that way in which C++ can support it.

When planning a program, you determine the core behaviors and the superstructure of the data model. Then, you build a computational model that incorporates both the behaviors and the data model. Indeed, you should think first about the data model, then the algorithms to operate upon it.

The standard library provides the most commonly-used linear data structures and algorithms that mutate them. Lists of various kinds happen to be the most convenient and easiest to model of the major data structures, and the functional paradigm teaches us that the most convenient algorithms for those data structures are the ones which the standard library chose to provide. The rest of C++ (classes, inheritance, functions, templates, etc.) provide a powerful way to model those data structures and algorithms efficiently, without sacrificing their genericity.

The way in which you choose to implement your data structures and algorithms doesn't matter to C++: It provides you with all of the tools you need to model computations in whatever form you find convenient. But that expressive breadth comes at the cost of complexity. Some models that you may choose may not be type-safe. C++ allows you to use them, but it also provides models that are type safe and generic.

Your question is, I think, the wrong one.

The question you should ask is not "should I use the standard containers or use objects," but rather, "What class of algorithms and data structures most clearly models my program?"

If you have a need for a simple data structure and the primary operations on that data structure are closely modeled by the standard algorithms library, by all means use it. They are part of the standard library because they are meant to be useful. It happens to be complete, in that it provides all of the high-level abstractions your program will ever need, but it may not always do so in a way that makes your code clear. This is why C++ provides all of its other tools: To give you a way to model your own kinds of abstractions.

5
  • +1 for making clear the difference between types and objects. Commented Mar 22, 2013 at 21:33
  • so my takeaway from this is that I should try create types that are based on standard containers so it's easier to work with them. and when i need to make the code clear, i should create object. the bottom line is that you don't have generic approach that solves everything, you have to mix things based on demand Commented Mar 22, 2013 at 21:40
  • No. Your takeaway should be that you should stop thinking that the standard containers are inherently in conflict with objects.
    – greyfade
    Commented Mar 22, 2013 at 23:26
  • well, isn't there a trade off? either you want to expose all the methods of standard containers or you want to minimize an interfaces of an object. Commented Mar 23, 2013 at 19:17
  • 1
    @kirill_igum: No. You want to expose the interface that is needed by code that uses it, and you don't generally want to expose an interface that is not needed. This is not an A or B choice. It's a continuous spectrum of choice that ranges from bare data structures to pure highly abstract interfaces and everything in between.
    – greyfade
    Commented Mar 23, 2013 at 19:43
1

I come from a background where most of my OO skills were gained using C#. However, most of my generic programming skills come from C++. I recently wrote a C++ project that recursively searched web sites for certain things (a web spider). I constantly ran into problems whenever I tried to mix OO and the STL.

Objects don't like to expose their internals. Those internals are the data structures (vectors, maps, etc.) that other objects want to interact with. It always felt clumsy to create accessor/mutator methods for these data structures. Consumers of my classes couldn't use the STL to grab and manipulate my data as they saw fit.

It is very easy to use the STL within the confines of a class. You have everything you need. But when you start interacting with other objects, using the STL is difficult without violating encapsulation. One topic I researched heavily was generic iterators (iterators that don't expose the underlying collection type). Even with generic iterators, your consumer needs to know whether the iterator is random access, forward, bi-drectional, etc.

Another approach I adopted later was passing functors to member functions. One object would pass a functor to another object's member function who would then pass it to an STL algorithm. At times I would have to decorate/adapt the functor to not expose implementation details about how data was stored internally. The problem with this approach was that it became difficult to know who "owned" a piece of functionality. Additionally, it meant that these member functions were templates, which limited where I could define their implementations. A lot of the problems I ran into with template member functions will be going away with C++11.

I ended up making classes that I felt were very exposed or whose implementations were spread out across too many other classes. A lot of this came from my desire to avoid writing explicit loops and avoiding inefficiencies. I believe on a professional project I would probably limit my use the STL to within the confines of my classes. I spent way too much time trying to use the STL everywhere I could.

By now it should be obvious that I'm probably not the best person to provide advice. I just wanted to share with you that the two styles are not always easy to combine. Bjarne Stroustrup's book The C++ Programming Language emphasizes how C++ was designed to allow programmers to switch between paradigms as needed. I don't think he intended the language to make it easy to combine them necessarily. Most of his examples regarding OOP touch the STL very little. He creates very distinct layers.

I'd recommend poking around my project to see how I used the STL across object bounds. Like I said, it's not perfect but it will provide some examples which may be useful.

1
  • you have a clear understanding of the problem I have, thank you for sharing your way to trying to solve it. Commented Mar 22, 2013 at 21:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.