ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
...
The second reason is that most base classes should have no data members (there are some major exceptions, though, which I admit I heavily rely upon.)
...
This is news to me. A base class should encapsulate the commonalities that are needed by derived classes. Why would anyone push the declaration of common member data to the derived classes? That would lead to the writing of duplicate code within each derived class.
Finally, I was interested in what dmail said. Were you suggesting that it should be:
Code:
const int& getType();
and
Code:
void setType(const int& t);
Perhaps I have misunderstood how references work under the hood, but wouldn't that take the same amount of work: copying a 32bit integer vs copying a 32bit pointer?
Thanks for all the help you've given already! It's much appreciated!
I think what dmail was suggesting is that another way to define/implement accessors is as follows:
For some, the notion of specifying 'get' and 'set' in the method name is superfluous, when all it takes is to see how the method is being used (i.e. called with a parameter or not).
This is news to me. A base class should encapsulate the commonalities that are needed by derived classes. Why would anyone push the declaration of common member data to the derived classes? That would lead to the writing of duplicate code within each derived class.
I did not say all. Before creating a base class, you need to ask yourself these things:
What separates a base class from a data member? The reason one uses a base class is so that the derived class can express its interface (either internally or externally.) If that interface isn't going to be expressed or implemented as a representation of the derived class then it should be a data member.
What does the interface of the base class require? The interface of a "most"-base class should only include a) what it needs to express, b) what it needs its derived classes to define in order for that to happen.
How will the base class utilize its derived classes? A base class is essentially pointless if it doesn't somehow utilize information in its derived classes. Base classes can utilize their derived classes either through pure virtual functions or by the derived classes actually defining the base class' interface so that the derived class can integrate with it functionality outside of the scope of the base class. Anything other than that makes the base class an isolated object within the derived class, also known as a data member, but one without a name.
How will the derived classes utilize the base class? As mentioned above, the derived classes must gain some sort of integrated benefit from the base class that results in it expressing the base class' interface in its own way, otherwise the base class is generally a waste. A base class isn't merely to "do something for me;" it's to "do something for my data or for my interface." The purpose of an interface is to a) provide a uniform front-end for an arbitrary back-end, b) hide what goes on behind it. With a base class that has many derived classes, it isn't uncommon for one or more of those derived classes to just be a wrapper or a container for yet another derived class (e.g. object selector, dynamic container.) For example, I have a system with a base class that utilizes a mutex to control access to its data (it has pure virtual functions for data retrieval and for the mutex,) a template class derived from it which implements the abstract interface, and a non-template derived class that dynamically stores instances of the template classes. All data members of the abstract class would go entirely to waste in the third class because it just encapsulates and passes on the functions of the encapsulated object; therefore, the template class contains a mutex object, whereas the third class just accesses the encapsulated object's mutex functions.
Where should the data be stored? Is this the concern of the base class? Only if the base class is derived from some other class to provide a common implementation of a common interface, and again, only if that's done in a way that doesn't inherently isolate that class when used as a base class itself. This implies that the "intermediate" class somehow needs to require something itself outside of the scope of the interface it's implementing, either through the inheritance of another base class or through the definition of its own pure virtual functions. For example, I have a base class that has a pure-virtual data exportation function. I have an intermediate class derived from it for exporting open/close-tag styles of data, which itself has pure virtual functions for getting the tags and the data from its derived classes.
What if multiple classes will require the same implementation? Create a member-free base class for passing as a function argument or storage as a pointer, then derive a class to implement it. This allows other classes implementing the interface to not be mandated to take on superfluous data members, but consolidates the common implementation. But again, you need to ask yourself why this is a base class and not just a data member; how does the class as a whole bidirectionally interact with the derived classes' unique data and interfaces?
These generalities obviously don't apply in all cases, but I think it adequately shows that most base classes with data members haven't been designed as well as they could have been. And by "most" I do mean "other than all;" it's just that I strongly believe that nearly all base classes should be interfaces and that very few should require data members between those interfaces and the most-derived classes. After writing all of that, I'm thinking back to my current projects to see how I can eliminate the "exceptions" I've allowed myself here
ta0kira
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.