Yes. Modularity is a fundamental part of programming. Breaking something down into smaller somethings is modularizing. In programming, you break a problem down into parts and then write functions, procedures, methods, or whatever the language calls them to handle those parts.
The term "modules" is also used to mean source files, but I don't think that's what you're specifically asking here.
In procedural programming, you focus on the steps you need to take in order to accomplish some task and pass your data around from function to function to accomplish the task. You break the steps down into smaller steps (functions in C/C++) in order to more easily accomplish the overall task of the program. This is modularizing. It helps reduce how much code you have to use (instead of copying/pasting the same code over and over, you put it into a function, make it work right and re-use it) as well as making it easier to understand the code. Think of how difficult it would be to read a simple section of a program that asks the user for his name, inputs the name and then displays the name if you had to put all the underlying code from cin and cout instead of just calling them with
cout << "Hi, " << name << endl;.
Here is an example of a procedural program in psuedocode:
Code:
start
initialize all the variables
show the main menu
ask for a menu choice
while the user hasn't picked the "quit" option
{
if the user picked option one, call the option one function
if the user picked option two, call the option two function
...
if the user picked an invalid option, show an error message to that effect
show the main menu
ask for a menu choice
}
end
Suppose this is a simple record keeping program and option 1 is to enter a new record, option 2 is to search for a specific record and so forth. You could represent the records as structs, and the program would be written such that all of the functions revolve around manipulating those structs; adding new ones, deleting existing structs from the list, displaying existing structs in the list, reading structs from the disk, writing structs to the disk, etc.
Object Oriented programming is a completely different way of thinking. At the highest level, instead of focusing on the steps you take to manipulate data as in procedural design, in object oriented programming you focus on what you are working with and then define how those things do their job. The objects you create model the things you are working with.
For example, you could create a card class to represent playing cards (that you can play poker, solitaire, blackjack, euchre, etc. with) and then a deck class to represent a deck of cards. You then define how those things interact. You could make the card objects able to compare themselves to each other, and then make the deck class able to shuffle and sort the cards and keep track of which cards have been dealt from the deck. Now, instead of having a bunch of functions to keep track of and worrying about calling the right ones in the right order, you would have something like the following:
Code:
Deck d; // just like creating an int or a float, except the Deck class constructor
// automatically creates 52 Card objects
Card mycard; // again, like creating an int or a float, except this makes a Card class object
Card anothercard;
d.shuffle(); // telling your deck object to shuffle the cards
mycard = d.deal(); // telling your deck object to deal the top card and storing the value
// of that card in the mycard variable
anothercard = d.deal();
if (mycard > anothercard)
cout << "My card was bigger." << endl;
else
cout << "My card was not bigger." << endl;
As you can see, instead of thinking about the program in terms of some data and a bunch of functions to manipulate that data, here we see the program in terms of the things we are trying to model. It is easy to understand what d.shuffle() means (assuming we gave the function an appropriate name), and it is obvious that we are comparing the value of one card to the value of the other card. What that card comparison is based on (rank of the card, suit, a combination of the two, or something else) is up to the designer of the Card class. You don't have to worry about how the deck will shuffle the cards (unless you are writing the .shuffle() function), instead you conceptually tell the deck to be shuffled.
Modularization here is more about the classes than the functions. Presumably when you have finished a class and are confident that it is working correctly, you can drop it in and tell it to do things in a more natural way, and visualize the object doing those things in your program. As you build the classes in a program, the relationships between the things you are modeling should make the program easier to understand, maintain and build upon. The string class is a good example. You don't worry about how the string is implemented and you can be pretty sure it's going to work as you expect. When you add 2 strings together with the + operator, you expect them to be added together like writing the 2nd string right after the first.
There is more (MUCH more) to object oriented programming, but classes are a fundamental concept for OOP. You can extend classes to an absurd level and have a Card class, a Deck class, a PokerDealer class that handles the deck, a Table class and a Player class to have a bunch of players sit down and play a game of poker at a table, a Casino class that employs the PokerDealer and perhaps handles other PokerDealers as well as SlotMachine's and RouletteWheel's and so forth, a City class that contans several Casino objects, and so on.
However, no matter how far you take classes or how deeply you dive into OOP, at the core of all programming is procedural programming. When you get down to it, the shuffle() function has to follow certains steps (a procedure) to accomplish its goal, and even within a class you'll find modularization in the form of writing private class functions to take care of things, as well as using other library functions, other classes and so on the same as if you were writing the main() function.
C++ is a tool however that allows you to write in whatever style you want, and even mix styles. You can write a completely procedural program, a completely object oriented program, you can use classes as more complex datatypes that know how to interact with the basic datatypes, you can write programs around a few objets, etc.
Also, not every situation calls for one or the other type of design. Sometimes object oriented programming is ideal to solve a problem, sometimes object oriented programming would make the design of a program more complex than a simple procedural design. Knowing both is good since you then have more than one tool in your toolbox.