1

Just started learning about classes in C++ and I'm have trouble understanding why object orientated programming (OOP) is useful. I understand the syntax, how to use them etc.

But I'm still confused as to why OOP is advantageous. Here are some specifics I'm having trouble with:

  1. Private variables. What is the use? Many sources tell me its to prevent outsiders from changing internal variables of the object, to protect the "insides". That doesn't make sense to me because wouldn't someone who wanted to change the variable just call the setter (mutator) functions and change it? Anyone can open the source file and call the setter and change the value of the variable. How is that "protection"? It's also mentioned that it makes debugging easier because instead of looking for every instance of the variable "x", you know "x" is only accessible through the class. So instead of ctrl+F "x" you just ctrl+F "memberFunction"?? How does that make debugging easier?

  2. I read somewhere that using getters and setters is bad. Although sometimes unavoidable, its generally bad. I read "Don't ask for the information you need to do the work; ask the object that has the information to do the work for you." Can someone explain why this is important?

  3. The big picture. I don't understand why implementing objects is more efficient than just if-statements and function calls....when there are functions in objects too. Objects don't seem to save tons of time in terms of coding. What am I missing?

1

3 Answers 3

2

Perhaps an example can help explaining the benefits of object oriented programming.

Consider a linked list, it consist of node structures containing some data and pointing to other nodes:

struct Node {
    Node* next;
    int data;
}

Assume a list of these (I named them for convenience):

Node c{null, 4};
Node b{&c, 73};
Node a{&b, 42};
Node* list = &a;

You can use this list as follows:

std::cout << list->data; // prints 42
std::cout << list->next->data; // prints 4

All is fine here, but imagine somewhere in your program the following happens:

Node d{&a, 17};
list->next->next = &d;

Now the list is messed up, it is: [a, b, d, a, b, d, …]; node c is lost and the list has become an endless repetition.

1a

To answer the first part of part 1 of your question, when Node::next is private the problematic assignment list->next->next = &d; can not happen.

1b & 2

Given a public setter:

void Node::setNext(Node* new_next) { this->next = new_next; }

As you say, then anyone can just use list->next->setNext(&d);. This leads to the answer to part two of your question: having a setter setNext() is bad. Lists should have modifying operations like insert(value), append(value), and remove(value).

This is an example of the general rule: classes should have operations that fit their intended meaning and use, not getters and setters for every field the implementation happens to have. Or the version you read: "Don't ask for the information you need to do the work; ask the object that has the information to do the work for you."

3

Your question, "I don't understand why implementing objects is more efficient than just if-statements and function calls", is a difficult one. First the word 'efficient' can have two meanings:

  1. the programs run faster and/or consume less resources
  2. writing a program takes less effort

For the first point running faster or consuming less resources, both object oriented programs and programs using if-statements and function calls can be efficient in this sense or very inefficient. For some problems thinking about them in an object oriented manner, leads to a more elegant and efficient solution than the if-statements and function calls approach. For other problems object oriented programming just gets in the way and causes overhead.

On the second interpretation of 'efficient': writing a program takes less effort.

  1. As @JB_King states object orientation helps to organize things that belong together.
  2. Once you have the list class, in other parts of the code you can think in terms of maintaining a list of 'x'es and sending a list of 'y's, instead of pointer manipulations. In addition when you look at the C++ standard library, the java runtime library, Boost Collection, Commons collections, Google guava, and others you'll find that others have already written List classes and that perhaps for your programming problem a list is not the best class but some other kind of collection.
    So once you have (or someone else has) written a class you can reuse it and you do not have to write it again. NOTE: of course the same holds for good libraries of functions, my answer is lacking a good explanation of why object oriented is better reusable than functional libraries.

Elaborations and side nodes

Even if you decide that this list class really does require a setNext()-method, then the method can have advantages over directly manipulating the Node::next-field. The method can perform extra checks; e.g.:

Node:setNext(Node* newNext) { if (this->next == null) { this->next = newNext; } else { throw new Error(); } }

Making fields private does not prevent malicious programmers/code from reading and manipulating the field; i.e.

class SecurityController {
private:
    std::string secretPassword;
};

and

struct SecurityController2 {
    std::string secretPassword;
}

are both equally (in)secure.

Declaring things private (and other methods of hiding implementation details) only helps well behaving programmers to create better code.

Initialization

Sometimes initializing an object is the only time that direct access to an object's fields is required. Then you can define a constructor that accepts and sets the field, e.g.:

Node::Node(int value_) {
    this->value = value_;
}

However, often there are better constructors that do not require the caller providing values. For example:

List::List() {
    …
}

to construct an empty List, and

List::List(std::iterator<int> start, std::iterator<int> end) {
    …
}

to create a list containing copies of the values from the C++ STL range [start, end>.

2
  • Thanks a lot, I enjoyed reading your explanation. Just one more question concerning setters. Obviously when a class instance is declared values need to be initialized. If: "classes should have operations that fit their intended meaning and use, not getters and setters for every field the implementation happens to have.", how should values in a class be initialized for use? If I have a member variable "int a", whats the best way to set a value to it? Only allow initialization at declaration like you did with your node example? Thanks again~
    – IanKZ
    Apr 22, 2014 at 14:04
  • @IanKZ edited to include initialization. Apr 22, 2014 at 15:17
2
  1. Note that you are assuming a setter always exists and can be modified. In some places, back-end code will be separate from front-end and there are only some ways to contact the back-end. In this case, private variables can be used to hide internal details from those using the code. This is highly important as a lot of code will exist in mult-tier environments where there may be a back-end platform that is separate from a front-end UI. Debugging can be easier because one can look for where the variable is used rather than having spaghetti code if properties get overly used or abused.

  2. This relates to the idea of what methods does the class do and what can be done outside of the class. Overusing properties can lead to a lot of code duplication that can cause problems if one wants to change the internal details of the class.

  3. How big is the largest coding project you've done? Have you programmed a shopping cart system with users and products? Without classes, how would you keep track of all the data that someone has in a cart? How do you handle the fact that the data from the database may contain relations that are better represented as objects than using a bunch of primitives that could get complicated as if you had lists for the names of products, prices of products and descriptions, a sort of any one list would trigger the others to also be sorted or else the data gets put into the wrong order.

2

Code that you produce might be consumed by third parties. As it's your code, it seems odd to you that you have to hide implementation details through private properties and methods. When you give this code to somebody else, they don't need to know how your code works, instead they need to know what it does.

In order to expose the "what it does" bit, you use public access modifiers. Imagine a vending machine. You drop a coin, select a product and the machine gives you a fizzy drink. Do you really need to know how the machine works? You don't all you care about is that you get a product after you put money in and press the button.

With regards to the setters and getters - yes, you can make them public. As soon as you do that, you expose implementation details to the consumer. Imagine you have three private properties and a method called "ServeDrink". You might choose to expose all three properties and a method through a public access modifier. You give this to somebody else. That person (consumer) looks at your API, sees public properties and starts using them freely. A month later, you decide to change how this works, there is still a function for serving a drink, but you no longer want to have three properties, instead you bring in a single property that aggregates old three properties. You give this to consumer.

Consumer of your API is now faced with a problem, where he though that it's OK to use three public properties, when it wasn't the case. Having said all this, you can try thinking of a consumer as an end user. By using OO design, you set limitations and boundaries on how your API should be used. You also state clear responsibilities. E.g. if something is public, you intend the consumer to use it, and if it's private, than the consumer shouldn't even be aware of it.

Try reading this story http://steve-yegge.blogspot.co.uk/2006/03/execution-in-kingdom-of-nouns.html - it's a fun read comparing function and OO kingdoms.

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