What benefit I will get to create an abstract class rather than the base class in CPP? - c++

In our project - C++, we have the generic module called "ContentCache". From this contentcache, we have derived the customer specific contentcache - for example - Airtel, TataSky. For example, the base contentCache has the method - create the database table, store the basic information. The other types of contentcache which has a relationship like airtel content cache is a type of contentcache. This airtel content cache is customized - overriden a few methods. However, the rest of it are the same. On a few products, we simply use the generic - contentCache. My question is do we need an abstract class - ContentCache - IcontentCache. Also, what is the good way - creating an abstract class or just create a generic base class. What advantage do we get with the IContentCache- i.e. abstract class. I am looking an answer from the design pattern point of view. Also, the programming point of view.

usually you use an abstract class if you define some functionality which can only be used if some additional, unavailable information (or functionality), is needed for that class to work. The unavailable but required information is defined as abstract methods of the class, then derived classes provide that extra information (or functionality).
In your example, if you can usefully have a generic ContentCache then it doesn't need to be abstract. But you might have a design where a ContentCache cannot be instantiated without knowing the name of the specific customer. In this case you might define all of the cache functionality in the abstract base class and have an abstract method which provides the name of the customer. Then in the derived classes you provide the implementation which returns that customer name and the class then has everything it needs to create the cache.
Admittedly this is not a great example as you could just provide the customer name in the constructor of the class, but you mention that in the derived classes you 'override a few methods'. These methods might be candidates for being abstract if they provide functionality which cannot be determined without knowing the customer.

Abstract class is better than just a normal base class. From the design perspective when ever we design a base class , we know that there is going to be inheritance (virtual functions). So we try to collect the common functions in the base class which will mostly be over ride in the derived class. Abstract means hiding the actual implementations from the outside world.Our implementations are our wealth.So base class needs to only work as an interface kind of thing and it should not have any implementation.
Abstract classes are good for you when ever your derived classes are going to ALWAYS use their derived class function definition rathar than using the base class definition.
Normal base classes will be useful , if you are going to use the base class virtual function definition along with the derived class function definition. Normal base class it will be good for small inheritance levels.

Related

c++ base class object to call unknown methods in subclasses

I am facing this problem:
An upstream application defines a class (e.g. box), and a member (say property) with a base class type. I would make a derived class for that member, add new members and methods without updating their application.
Essentially I do box->property = make_shared<myProperty>(). Is there a way to keep the interface of calling the members and methods the same? That is, to access a property using box->property->length or box->property->GetWeight(), rather than dynamic_pointer_cast<myProperty>(box->property)->GetWeight(). The challenge here is they won't update the base property class, and I am not supposed to change box. But we wish to keep the interface the same so our customers won't complain.
Is it possible? If not, how could we do to best keep the main app and my plugin relatively independent while minimize the changes on the customer side? Any suggestions are welcome.
Looks to me like the derived class for that member property violates Liskov's substitution principle.
You mentioned not being able to modify the Box class.
But are you allowed to modify the property base class? I suggest you add your "additional" methods of your derived class to the property base class.
The intent here being that the interface between the base and derived class should be one and the same. So do this only if it makes sense design wise.

When to declare protected fields in abstract class cpp

I feel very uncomfortable with the concept of abstract classes, and I'd be happy if someone could make it a bit clearer. I do understand that it's also a matter of implementation and personal style, but I'd like to have at least some guidelines to think about when trying to solve a problem.
I thought that abstract classes only represent a type of behavior that their derived classes will inherit. since we cannot instantiate an object from an abstract class type, so if they have a c'tor or any data fields, they should be in protected mode. I've encountered a piece of code today, where the abstract class had a public constructor and it made me even more confused. I have few questions about this:
the only unique thing about abstract classes is that they have pure virtual functions? it's the only thing that prevents me from instantiating object from this class
on what occasions do I want to declare protected fields in an abstract class? when is it useful to add protected constructor? when is a public constructor needed?
I see many different uses of abstract classes, but sometimes I think about totally different solution, which most of the times is much more complicated and cumbersome than the one presented.
Thank you for your time and attention everyone.
Use abstract classes when you want to provide a base implementation for something, leave some parts of the implementation up to the child classes, but make it mandatory to implement the bits and pieces that are missing.
the only unique thing about abstract classes is that they have pure virtual functions?
A class is abstract because some parts of it (methods) are abstract too (have no implementation).
However, you can declare a class as abstract even if it has no abstract method. That is you want to prevent people from instantiating it. (you could in that case also declare the constructor protected)
on what occasions do I want to declare protected fields in an abstract class?
On the same occasion you would declare protected fields for any class: some properties which may be used by child classes
when is it useful to add protected constructor?
When you want to prevent instantiation of objects of a class. If the class is abstract, there is no additional benefit as it will not be intantiable anyway.
when is a public constructor needed?
For abstract classes, it is not. But that is valid. That constructor will then be used by child classes to pass parameters from their own constructors. In the case of abstract classes it may be declared protected without any side effect.
Kindly note that I am no C++ expert, but those questions are valid in any OOP language.

Class design to avoid need for list of base classes

I'm currently in the design phase of a class library and stumbled up on a question similar to "Managing diverse classes with a central manager without RTTI" or "pattern to avoid dynamic_cast".
Imagine there is a class hierarchy with a base class Base and two classes DerivedA and DerivedB that are subclasses of Base. Somewhere in my library there will be a class that needs to hold lists of objects of both types DerivedA and DerivedB. Further suppose that this class will need to perform actions on both types depending on the type. Obviously I will use virtual functions here to implement this behavior. But what if I will need the managing class to give me all objects of type DerivedA?
Is this an indicator of a bad class design because I have the need to perform actions only on a subset of the class hierarchy?
Or does it just mean that my managing class should not use a list of Base but two lists - one for DerivedA and one for DerivedB? So in case I need to perform an action on both types I would have to iterate over two lists. In my case the probability that there will be a need to add new subclasses to the hierarchy is quite low and the current number is around 3 or 4 subclasses.
But what if I will need the managing class to give me all objects of
type DerivedA?
Is this an indicator of a bad class design because I have the need to
perform actions only on a subset of the class hierarchy?
More likely yes than no. If you often need to do this, then it makes sense to question whether the hierarchy makes sense. In that case, you should separate this into two unrelated lists.
Another possible approach is to also handle it through virtual methods, where e.g. DeriveB will have a no-op implementation for methods which don't affect that. It is hard to tell without knowing more information.
It certainly is a sign of bad design if you store (pointers to) objects together that have to be handled differently.
You could however just implement this differing behaviour as an empty function in the base class or use the visitor pattern.
You can do it in several ways.
Try to dynamic_cast to specific class (this is a bruteforce solution, but I'd use it only for interfaces, using it for classes is a kind of code smell. It'll work though.)
Do something like:
class BaseRequest {};
class DerivedASupportedRequest : public BaseRequest {};
Then modify your classes to support the method:
// (...)
void ProcessRequest(const BaseRequest & request);
Create a virtual method bool TryDoSth() in a base class; DerivedB will always return false, while DerivedA will implement the required functionality.
Alternative to above: Create method Supports(Action action), where Action is an enum defining possible actions or groups of actions; in such case calling DoSth() on class, which does not support given feature should result in thrown exception.
Base class may have a method ActionXController * GetControllerForX(); DerivedA will return the actual controller, DerivedB will return nullptr.
Similarly, base class can provide method: BaseController * GetController(Action a)
You asked, if it is a bad design. I believe, that it depends on how much functionality is common and how much is different. If you have 100 common methods and only one different, it would be weird to hold these data in separate lists. However, if count of different methods is noticeable, consider changing design of your application. This may be a general rule, but there are also exceptions. It's hard to tell without knowing the context.

Why can't we create an instance of an abstract class?

I found in many places that :
An Abstract Class is a class which is supposed to be used as a base class.
An Abstract Class is a class which has atleast one Pure Virtual Function.
But one thing that always strikes my mind is why can't we create an instance of an abstract class? Many places on the Internet say there is no point in creating an instance, or some say that they are supposed to be used as base classes. But why is it an error to create an instance of an abstract class?
Your void bar()=0; is not valid -- the =0 notation can only be used with virtual functions.
The whole point of an abstract class is that it's abstract -- you've defined an interface but not an implementation. Without an implementation, instantiating the class wouldn't produce a meaningful or useful result. If it does/would make sense to instantiate objects of that class, then you simply don't want to use an abstract class in the first place.
For example, consider device drivers. We might have a driver for an abstract storage device. We define some capabilities for that device, such as reading and writing data. That abstract class gives any code that wants to read/write data the ability to work with an concrete class that derives from that abstract class.
We can't just instantiate our abstract storage device though. Instead, we need a concrete object like a thumb drive, disk drive, etc., to actually read from/write to. The concrete class is needed because we need code specific to the actual device to carry out the commands we've defined in our abstract base. Our abstract storage class just has a read or write, but do the reading or writing, we need a driver for a specific device. One might know how to talk to a SATA hard drive, while another knows how to talk to a USB thumb drive and a third knows how to read from or write to an SD card. We can't, however, just say "I'm going to create an abstract storage device", and talk to it without defining the actual code that will translate a "write" command into (for example) the right signals going over SATA, USB, Firewire, etc., to get the data onto a real drive.
As such, attempting to instantiate our abstract class makes no sense, and isn't allowed. We just use the abstract base class so the rest of the system can deal with all devices uniformly. The rest of the code doesn't care how the signals are different from each other -- it just sees a bunch of disk drives, and can work with all of them, even though the details of reading data over USB are completely different from reading over Firewire (for example).
An abstract class represents something that isn't specific enough to be instantiated. For instance, what if someone asked you to create a vehicle? You'd have to ask, "what kind of vehicle?" You wouldn't know whether to create a car, a sled, or a space shuttle. There's no such object as a "vehicle". Yet "vehicle" is a useful abstraction that can be used to group objects, indicating common behaviors among them. That's what abstract classes are for.
An abstract class is more than an interface. It may have data members. It may have member functions that are not pure virtual, or non-virtual at all. Even a pure virtual function may have a body, providing a default implementation. So this is not about a physical impossibility of instantiating an abstract class.
The main point is that a pure virtual function is a virtual function that must be overridden by a derived class. That means that a derived class must be defined, and the way to force that is to forbid the instantiation of an abstract class.
An abstract class is not specific enough to be instantiated. Not necessarily because it is missing a definition of a function, because it may not be missing it. It is not specific enough because it represents an abstract concept, which must be made more specific before it can be instantiated.
That's the whole point of an abstract class: that some details must be provided by the implementor.
Think about it: what would be the point of marking a class as abstract if you could instantiate it directly? Then it would be no different than any other class.
The reason an abstract class cannot be instantiated is: what do you do if you execute the pure virtual function? That would be a serious error, and it's better to catch that at compile-time than at runtime.
In abstract class no method definition is given, only structure is provided. If we could instantiate abstract class and call those method, it will be a huge mess. Abstract class is use to maintain a design pattern of the code.
Only Chuck Norris can instantiate an abstract class.
https://api.chucknorris.io/jokes/ye0_hnd3rgq68e_pfvsqqg

What is special about the abstract class mechanism in C++?

I have question that bothers me for few days.
Abstract class is a special type of class that we cannot instantiate, right?. (Which is denoted/specified by giving a "= 0" to at least one method declaration, which looks like an afterthought).
What are the extra benefits that the abstract class mechanism brings to C++, that a 'normal' base class cannot achieve?
According to the wikibooks section on abstract classes:
It's a way of forcing a contract between the class designer and the users of that class. If we wish to create a concrete class (a class that can be instantiated) from an abstract class we must declare and define a matching member function for each abstract member function of the base class.
As mentioned, it's a way of defining an interface to which derived classes must adhere. Their example of the Vehicle abstract class is very apropos: you'd never have just a Vehicle in real life, you'd have a Ford Explorer or a Toyota Prius, but those both conform to (for the sake of argument) a base set of functionality that being a Vehicle might define. But, you can't just go to the Vehicle dealership and drive a Vehicle off the lot. Thus, you'd never want to be able to construct and use a base Vehicle object where you'd really want a specialized, derived object.
This offers the best way in C++ to define an interface without any default implementation.
C++ does not have C#'s interface concept.
It's the equivalent of what Java turned into "interfaces". Basically, it implies that the class itself is not usable - you need to override all pure methods.
An example is MFC's CView class which has a pure OnDraw method - the basic CView doesn't do anything and is as such useless. You have to override OnDraw.
(Btw - it is still possible to provide an implementation for a pure method, and subclassed implementations can fall back to it, but they still have to provide their own override.)
They are used as a base class in a class hierarchy design.
Abstract classes are used to define a clean interface for all derived classes.
At design stage, abstract classes define an interface, per specification and derived classes implement the desired functionality accordingly.
Also using abstract classes instead of "normal" classes helps separating the implementation details from the interface.
A concrete class implements an interface, but the abstract class defines it. You could use a concrete class as a base class in your design but abstract classes are not meant to be used directly in code and can not be instantiated. They serve as prototype.
By using the "normal" class as you say, you have to define an implementation for all methods.
Don't think of it at the class level.
Look at the method, and think of what it should do in the default case:
virtual std::string getName() const = 0;
What would be a right implementation for this method ? There is none than I can think of.
By marking it "pure virtual", you ensure that if the user ever get an instance of a class derived from your interface, then this method will have a sensible behavior.
The only other way to do this would be a throw NotImplemented("getName"); body, but then you'd discover the issue at runtime, not at compile-time, which is not as nice :)