Originally Posted by
marcoesteves
I want to learn OOP, so, I'll try to understad.
Assuming there are a main function which calls the "debugs".
I think the 1st one, after the class declaration, it will be called as debug(const int& mycolor_value) and it will print the value of mycolor_value, as an acessor function.
The 2nd one will be called as colorObject.debug(const int& mycolor_value). This one will print mycolor_value like an acessor function.
The 3rd I'm not so sure. I think that will print nothing since m_mycolor_value is a private variable.
You need to think about what functions are good where, how objects help and why. Classes are great when you need to group dependent data and perform actions upon those.
In my example, all three functions do the same thing, but their interface differs. Since we have a color class, which of the function are more appropriate, especially considering that m_mycolor_value is private (i.e. the users of the class cannot access it)?
Your answer for the 3rd is completely incorrect, making me believe you do not understand encapsulation and access modifiers yet. You should probably brush up on this.
Now let's take an example. The Music CD class.
We have something abstract: an idea, perhaps something concrete that can be touched, felt. We need to make a decision on how to model this.
So first of, what do a music cd consist of?
It has an author, (total) length and tracks (and perhaps more).
So what can we do with a music cd (i.e. operations)?
At this point, we can imagine setting and getting all of its properties (e.g. set/get author, length and tracks).
Now, how can we model this?
We could have an array of authors, lengths and an array of arrays of tracks, but this spreads highly correlated data around, so we should probably group them. E.g.:
Not:
Code:
std::array<std::string, N> Author;
std::array<int, N> Length;
std::array<std::vector<XTrackInfo>, N> TrackInfo;
Instead:
Code:
struct XMusicCd
{
std::string Author;
int Length;
std::vector<XTrackInfo> TrackInfo;
};
std::array<XMusicCd, N> MusicCd;
This groups correlated data together. Now let's define operations. Since they're just getters and setters, we really don't have to do anything at all, but let's just do that for the example's sake. So we would have:
void SetAuthor(XMusicCd& Cd, std::string Author);
const std::string& GetAuthor(XMusicCd& Cd);
// ...
So what do these operation functions need? That is, what information must they take, and where do they get that information? Well, we said that they operated on CDs, so obviously you must tell them what CD they should operate on. Hence, the first argument is the CD. For set, the function must know the new author to set. This information must come from the user since the user wants to set a new user. Hence, the set function takes another argument.
But note that both functions take a reference to the CD. This implies that they are operations for CDs and are highly correlated to the CD data (i.e. they need access to the CD data). So we could group these operations together with the data:
Code:
class XMusicCd
{
private:
std::string m_Author;
int m_Length;
std::vector<XTrackInfo> m_TrackInfo;
public:
void SetAuthor(std::string Author);
const std::string& GetAuthor() const;
};
std::array<XMusicCd, N> MusicCd;
Now the the CD they operate on is *this, so we don't need the user to tell us which CD to operate on by passing another argument. This is implicit since the user invokes the function on the object (i.e. CD) to operate on.
Now, the set author wants to set the author of the CD, and it has access to the CD to set the author on. So where is the information it should modify? It should be obvious that it is (*this).Author. After all, set author implies that we should set the Author member on the object the function was invoked on.
How about GetAuthor then? GetAuthor must know from which object to get the author from. Following the same logic, we know what object it operates on, i.e. *this. So the implementations of these functions would be:
Code:
void SetAuthor(std::string Author) { m_Author = Author; }
const std::string& GetAuthor() const { return m_Author; }
Now I ask you: which of the following functions would be appropriate for Length and how would you implement them?
Code:
void SetLength(XMusicCd& Cd, int Length);
void XMusicCd::SetLength(XMusicCd& Cd, int Length);
void XMusicCd::SetLength(int Length);
int GetLength(XMusicCd& Cd);
int XMusicCd::GetLength(XMusicCd& Cd) const;
int XMusicCd::GetLength() const;
Note that this is just a basic modelling example. In the real world, you have to consider other things, such as how much code duplication, maintainability, difficulty of implementation, etc. But this is a good starting point.