20

I've just learned about polymorphism in my OOP Class and I'm having a hard time understanding how abstract base classes are useful.

What is the purpose of an abstract class? What does defining an abstract base class provide that isn't provided by creating each necessary function in each actual class?

Chris Dargis
  • 5,891
  • 4
  • 39
  • 63
Yoshua Joo Bin
  • 517
  • 3
  • 6
  • 15
  • 6
    The point is that you *do* create the function in each class. It's enforced by the compiler. – chris Jan 07 '13 at 03:25

10 Answers10

26

The purpose of an abstract class is to define a common protocol for a set of concrete subclasses. This is useful when defining objects that share code, abstract ideas, etc.

Abstract classes have no instances. An abstract class must have at least one deferred method (or function). To accomplish this in C++, a pure virtual member function is declared but not defined in the abstract class:

class MyClass {
    virtual void pureVirtualFunction() = 0;
}

Attempts to instantiate an abstract class will always result in a compiler error.

"What does defining an abstract base class provide that isn't provided by creating each necessary function in each actual class?"

The main idea here is code reuse and proper partitioning across classes. It makes more sense to define a function once in a parent class rather than defining over and over again in multiple subclasses:

class A {
   void func1();
   virtual void func2() = 0;
}

class B : public A {
   // inherits A's func1()
   virtual void func2();   // Function defined in implementation file
}

class C : public A {
   // inherits A's func1()
   virtual void func2();   // Function defined in implementation file
}
Chris Dargis
  • 5,891
  • 4
  • 39
  • 63
20

Having an abstract class like "Dog" with a virtual method like "bark" allows all classes that inherit from Dog to have their bark code called in the same way, even though the Beagle's bark is implemented way differently than the Collie's.

Without a common abstract parent (or at least a common parent with a bark virtual method) it'd be difficult to do the following:

Have a Vector of type Dog that contains Collies, Beagles, German Shepherds etc and make each of them bark. With a Vector of Dogs that contains Collies, Beagles, German Shepherds all you would have to do to make them all bark is to iterate through in a for loop and call bark on each one. Otherwise you'd have to have a separate Vector of Collies, Vector of Beagles etc.

If the question is "why make Dog abstract when it could be concrete, have a virtual bark defined with a default implementation that can be overriden?", the answer would be that this may be acceptable sometimes -- but, from a design perspective, there really isn't any such thing as a Dog that isn't a Collie or a Beagle or some other breed or mix so although they are all Dogs, there is not one of them in reality that is a Dog but not some other derived class too. Also, since dogs barking is so varied from one breed to another, there is unlikely to be any real acceptable default implementation of bark that would be acceptable for any decent group of Dogs.

I hope this helps you understand the purpose: yes, you're going to have to implement bark in each subclass anyway, but the common abstract ancestor lets you treat any subclass as a member of a base class and invoke behaviors that may be conceptually similar like bark but in fact have very different implementations.

Chris
  • 221
  • 2
  • 3
9

Abstract classes allow for compile time protocol enforcement. These protocols define what it means to be a part of a class family.

Another way to think of it is that a abstract class is a contract that your implementing classes must fulfill. If they do not fulfill this contract they cannot be part of the class family and they must be modified to conform to the contract. The provided contract may provide default functionality, but it also leaves it up to the sub-class to define more specific or different functionality while still remaining within the scope of the contract.

For small projects this may not seem useful but for large projects it provides conformity and structure as it provides documentation through the abstract class contract. This makes for more maintainable code and makes for the sub-classes to each have the same protocol making using and developing new sub-classes easier.

sean
  • 3,955
  • 21
  • 28
3

The purpose of an abstract class is to provide an appropriate base class from which other classes can inherit. Abstract classes cannot be used to instantiate objects and serves only as an interface. Attempting to instantiate an object of an abstract class causes a compilation error. (because vtable entry is not filled with memory location for virtual function we mentioned in Abstract Class)

Thus, if a subclass of an ABC needs to be instantiated, it has to implement each of the virtual functions, which means that it supports the interface declared by the ABC. Failure to override a pure virtual function in a derived class, then attempting to instantiate objects of that class, is a compilation error.

Example:

class mobileinternet
{
public:
virtual enableinternet()=0;//defines as virtual so that each class can overwrite
};


class 2gplan : public mobileinternet

{
    private:

         int providelowspeedinternet(); //logic to give less speed.

    public:

         void enableinternet(int) {
                                     // implement logic
                                 }

};

//similarly

class 3gplan : public enableinternet
{
   private: high speed logic (different then both of the above)

   public: 
          /*    */
}

here in this example, you can understand.

bummi
  • 27,123
  • 14
  • 62
  • 101
2

I have a dog. Abstract class dog with a method bark. My particular dog makes one bark. Other dogs bark in a different way. So defining a dog in the abstract way is useful.

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • when we want to override the bark method in derived class, we actually create the function bark in each derived class. So could you give me the specific reason why it is impotant to be used ? – Yoshua Joo Bin Jan 07 '13 at 03:33
  • 1
    inherent class to the a specific contract that a dog must implement the bark function. Other wise you will not enable to initiate the class. Assume that the subclass is implemented by a third party. This abstract mechanism insure that the third party implements the bark, and polymorphism can be used safely when calling the bark function from abstract dog perspective. – Hagai Jan 07 '13 at 03:38
0

Abstract classes are used to define an interface to be implemented. See some references:

http://en.wikibooks.org/wiki/C%2B%2B_Programming/Classes/Abstract_Classes

OldProgrammer
  • 12,050
  • 4
  • 24
  • 45
0

An abstract class AbstractClass as a base class is needed when there is functionality that is desired for all objects that have a type deriving from AbstractClass, but cannot sensibly be implemented on the AbstractClass itself.

The old and somewhat artificial OO example of having a base class Vehicle with derived classes Car, Motorcycle, ... provides a good example here, say you want a method move() - you can implement the way that a Car or a Motorcycle moves, but Vehicles don't move in a generic way, so Vehicle::move() will have to be pure virtual and Vehicle therefore abstract.

us2012
  • 16,083
  • 3
  • 46
  • 62
0

why don't we create each necessary function in each class ? (C++)

You have to create each necessary function marked as abstract in each derived class.

If you question is, why to create abstract function in abstract class?

It allows strict run time polymorphism.

Also read Interface vs Abstract Class (general OO)

Community
  • 1
  • 1
Tilak
  • 30,108
  • 19
  • 83
  • 131
  • Nice i got it, if i'm using abstract class i can classified them into a group. And i can cast them by using static and dynamic cast with a base pointer. – Yoshua Joo Bin Jan 07 '13 at 04:16
0
abstract class dog
{
bark();
}

// function inside another module

dogbarking(dog obj)
{
   dog.bark(); // function will call depend up on address inside the obj
}


// our class
ourclass: inherit dog
{
    bark()
    {
         //body
     }
}


main()
{
    ourclass obj;
    dogbarking(obj);
}

we can see that dogbarking is a function written in another module. it knows only the abstract class dog. even though it can call the function bark inside ourclass. in main function we create object of ourclass and pass to function dogbarking where it received using reference object of abstract class dog.

Pranav
  • 8,563
  • 4
  • 26
  • 42
Rajesh
  • 182
  • 1
  • 2
  • 9
0

Imagine you have two methods for displaying a string:

DisplayDialog(string s);
PrintToConsole(string s);

And you want to write some code that can be switched between these two methods:

void foo(bool useDialogs) {
    if (useDialogs) {
        DisplayDialog("Hello, World!");
    } else {
        PrintToConsole("Hello, World!");
    }

    if (useDialogs) {
        DisplayDialog("The result of 2 * 3 is ");
    } else {
        PrintToConsole("The result of 2 * 3 is ");
    }

    int i = 2 * 3;
    string s = to_string(i);

    if (useDialogs) {
        DisplayDialog(s);
    } else {
        PrintToConsole(s);
    }        
}

This code is tightly coupled to the specific methods used for displaying the string. Adding an additional method, changing how the method is selected, etc. will affect every piece of code that uses this. This code is tightly coupled to the set of methods we use to display strings.

Abstract base classes are a way of decoupling code that uses some functionality from the code that implements that functionality. It does this by defining a common interface to all the various ways of doing the task.

class AbstractStringDisplayer {
public:
    virtual display(string s) = 0;

    virtual ~AbstractStringDisplayer();
};

void foo(AbstractStringDisplayer *asd) {
    asd->display("Hello, World!");
    asd->display("The result of 2 * 3 is ");

    int i = 2 * 3;
    string s = to_string(i);

    asd->display(s);
}

int main() {
    AbstractStringDisplayer *asd = getStringDisplayerBasedOnUserPreferencesOrWhatever();

    foo(asd);
}

Using the interface defined by AbstractStringDisplayer we can create and use as many new ways of displaying strings as we want, and code that uses the abstract interface won't need to be changed.

bames53
  • 86,085
  • 15
  • 179
  • 244