13

I am studying OOP in C++ and, even though I am aware of the definitions of these 3 concepts, I cannot really realize when or how to use it.

Let's use this class for the example:

class Person{
    private:
             string name;
             int age;
    public:
             Person(string p1, int p2){this->name=p1; this->age=p2;}
             ~Person(){}

             void set_name (string parameter){this->name=parameter;}                 
             void set_age (int parameter){this->age=parameter;}

             string get_name (){return this->name;}
             int get_age (){return this->age;}

             };

1.Singleton

HOW does the restriction of the class to have only one object work?

CAN you design a class that would have ONLY 2 instances? Or maybe 3?

WHEN is using a singleton recommended/necessary? Is it good practice?

2.Abstract Class

As far as i know, if there's only one pure virtual function, the class becomes abstract. So, adding

virtual void print ()=0;

would do it, right?

WHY would you need a class whose object is not required?

3.Interface

If an interface is an abstract class in which all the methods are pure virtual functions, then

WHAT is the main difference between the 2 of them?

Thanks in advance!

3
  • 2
    Singleton is controversial, do a search for it on this site to get various opinions. May 7, 2012 at 23:05
  • 2
    It's also worth noting that while abstract classes are part of the language, neither singletons or interfaces are. They are patterns that people implement. Singleton in particular is something that requires a bit of clever hacking to make work. (Though of course you can create a singleton by convention only.) May 7, 2012 at 23:10
  • 1
    One at a time please.
    – JeffO
    May 8, 2012 at 21:33

7 Answers 7

18

1. Singleton

You restrict the number of instances because the constructor will be private meaning only static methods can create instances of that class (there are other dirty tricks actually to accomplish that but let's not get carried away).

Creating a class that will have only 2 or 3 instances is perfectly feasible. You should be using singleton whenever you feel the necessity to have only one instance of that class in the entire system. That usually happens to classes that have a 'manager' behavior.

If you want to learn more about Singletons you can start in Wikipedia and particularly for C++ in this post.

There is definitely some good and bad things about this pattern but this discussion belongs somewhere else.

2. Abstract Classes

Yes, that's right. Only a single virtual method will mark the class as abstract.

You'll be using those kind of classes when you have a bigger class hierarchy in which the top classes should not really be instantiated.

Let's supposed you're defining a Mammal class and then inheriting it to Dog and Cat. If you think about it, there's no much sense to have a pure instance of a Mammal since you first need to know what kind of Mammal it really is.

Potentially there's a method called MakeSound() that will only make sense in the inherited classes but there's no common sound that all mammals can make (It's just an example not trying to make a case for mammal's sounds here).

So that means Mammal should be an abstract class since it will have some common behavior implemented to all mammals but it's not really supposed to be instantiated. That's the basic concept behind abstract classes but there's definitely more to it that you should learn.

3. Interfaces

There are no pure interfaces in C++ in the same sense that you have in Java or C#. The only way to create one is by having a pure abstract class which mimics most of the behavior you want from an interface.

Basically the behavior you're looking for is to define a contract where other objects can interact with without caring about the underlying implementation. When you make a class purely abstract it mean all implementation belongs somewhere else so the purpose of that class is only about the contract it defines. This is a very powerful concept in OO and you should definitely look more into it.

You can read about the interface specification for C# in MSDN to have a better idea:

http://msdn.microsoft.com/en-us/library/ms173156.aspx

C++ will provide the same kind of behavior by having a pure abstract class.

8
  • 2
    A pure abstract base class gives you everything an interface does. Interfaces exist in Java (and C#) because the language designers wanted to prevent multiple inheritance (because of the headaches it creates) but recognized a very common usage of multiple inheritance that is not problematic. May 7, 2012 at 23:14
  • @StevenBurnap: But not in C++, which is the context of the question.
    – DeadMG
    May 7, 2012 at 23:28
  • 3
    He's asking about C++ and interfaces. "Interface" is not a language feature of C++, but people do certainly create interfaces in C++ that work exactly like Java interfaces, using abstract base classes. They did so before Java even existed. May 7, 2012 at 23:39
  • See accu.org/index.php/journals/233. May 7, 2012 at 23:41
  • 1
    Same is true of Singletons. In C++, both are design patterns, not language features. This doesn't mean people don't talk about interfaces in C++ and what they are for. The concept of "interface" came out of component systems like Corba and COM, which were both originally developed to be used in pure C. In C++, interfaces are typically implemented with abstract base classes in which all methods are virtual. The functionality of this is identical to that of a Java interface. As such, the concept of a Java interface is intentionally a subset of C++ abstract classes. May 8, 2012 at 23:35
8

Most people already explained what singletons/abstract classes are. Hopefully, I'll provide a little different perspective and give some practical examples.

Singletons - When you want all calling code to use a single instance of variables, for whatever reasons, you have the following options:

  • Global variables - obviously no encapsulation, most of the code coupled to globals... bad
  • A class with all static functions - a little better than simple globals, but this design decision still leads you towards a path where code relies on global data and could be very hard to change later. Also you can't take advantage of OO things like polymorphism if all you have is static functions
  • Singleton - Even though there's only one instance of the class, the actual implementation of the class doesn't have to know anything about the fact that it is global. So today you can have a class that's a singleton, tomorrow you can simply make its constructor public and let clients instantiate multiple copies. Most client code that references the singleton wouldn't have to change and implementation of the singleton itself won't have to change. The only change is how the client code acquires singleton reference in the first place.

Of all the evil and bad options out there, if you do have a need for global data, singleton is a MUCH better approach than either of the previous two. It also allows you keep your options open if tomorrow you change your mind and decide to use inversion of control instead of having global data.

So where would you use a singleton? Here's few examples:

  • Logging - if you want your entire process to have a single log, you could create a log object and pass it around everywhere. But what if you have 100,000k lines of legacy application code? modify all of them? Or you could simply introduce the following and start using it anywhere you please:

    CLog::GetInstance().write( "my log message goes here" );
    
  • Server connection cache - This was something I had to introduce in our application. Our code base, and there was a lot of it, used to connect to servers whenever it pleased. Most of the time this was ok, unless there was any kind of latency in the network. We needed a solution and redesign of a 10 year old application wasn't really on the table. I wrote a singleton CServerConnectionManager. Then I searched through the code and replaced CoCreateInstanceWithAuth calls with identical signature call that invoked my class. Now after the first attempt connection was cached and the rest of the time "connect" attempts were instantaneous. Some say singletons are evil. I say they saved my butt.

  • For debugging, we often find global running object table to be very useful. We have some classes we would like to keep track of. They all derive from the same base class. During instantiation, they call the object table singleton and register themselves. When they are destroyed, they unregister. I can walk up to any machine, attach to a process and create a list of running objects. Been in the product for over half a decade and I never felt that we ever had a need for 2 "global" object tables.

  • We have some relatively complex string parser utility classes which rely on regular expressions. Regular expression classes needs to be initialized before it can perform matches. The initialization is somewhat expensive because that's when an FSM is generated based on parse string. However after that, regular expression class can be safely accessed by 100 threads because once built FSM never changes. These parser classes internally use singletons to make sure this initialization happens only once. This significantly improved performance and never caused any problems due to "evil singletons".

Having said all this, you do need to keep in mind when and where to use singletons. 9 out of 10 times there's a better solution and by all means, you should use that instead. However, there are times when singleton is absolutely the right design choice.

Next topic... interfaces and abstract classes. First as others have mentioned, interface IS an abstract class but it goes beyond that by enforcing that it has absolutely NO implementation. In some languages interface keyword is part of the language. In C++ we simply use abstract classes. Microsoft VC++ took one step to define this somewhere internally:

typedef struct interface;

... so you can still use the interface keyword (it'll even be highlighted as a 'real' keyword), but as far as the actual compiler is concerned, it's just a struct.

So where would you use this? Let's go back to my example of a running object table. Let's say the base class has...

virtual void print() = 0;

There's your abstract class. Classes that use runtime object table will all derive from the same base class. Base class contains common code for registering/unregistering. But it will never be instantiated by itself. Now I can have deriving classes (e.g. requests, listeners, client connection objects...), each one will implement print() so that when attach to the process and ask it, what is running, each object will report it's own state.

Examples of abstract classes/interfaces are countless and you definitely use (or should use) them much, much more frequently that you would use singletons. In short, they allow you to write code that works with base types and isn't tied to actual implementation. This allows you to modify implementation later without having to change too much code.

Here's another example. Let's say I have a class that implements a logger, CLog. This class writes to the file on local disk. I start using this class in my legacy 100,000 lines of code. All over the place. Life is good until someone says, hey let's write to the database instead of a file. Now I create new class, let's call it CDbLog and writes to the database. Can you imaging the hassle of going through 100,000 lines and changing everything from CLog to CDbLog? Alternatively, I could have:

interface ILogger {
    virtual void write( const char* format, ... ) = 0;
};

class CLog : public ILogger { ... };

class CDbLog : public ILogger { ... };

class CLogFactory {
    ILogger* GetLog();
};

If all of the code was using ILogger interface, all I would have to change is internal implementation of CLogFactory::GetLog(). The rest of the code would just automagically work without me having to lift a finger.

For more information on interfaces and good OO design, I would strongly recommend Uncle Bob's Agile Principles, Patterns, and Practices in C#. The book is filled with examples that use abstractions and provides plain language explanations of everything.

4

WHEN is using a singleton recommended/necessary? Is it good practice?

Never. Worse than that, they're an absolute bitch to get rid of, so making this mistake once can haunt you for many, many years.

The difference between abstract classes and interfaces is absolutely nothing in C++. You generally have interfaces to specify some behaviour of the derived class, but without having to specify all of it. This makes your code more flexible, because you can swap out any class that meets the more limited specification. Run-time interfaces are used when you need a run-time abstraction.

4
  • Interfaces are a subset of abstract classes. An interface is an abstract class with no defined methods. (An abstract class with no code at all.) May 7, 2012 at 23:16
  • 1
    @StevenBurnap: Maybe in some other language.
    – DeadMG
    May 7, 2012 at 23:26
  • 4
    "Interface" is just a convention in C++. When I've seen it used, it's an abstract class with only pure virtual methods and no properties. Obviously you can write any old class and slap an "I" in front of the name. May 7, 2012 at 23:37
  • This is the way I expected people to answer this post. One question at a time. Anyway, Thank you a lot guys for sharing your knowledge. This community is worth investing time in.
    – appoll
    May 12, 2012 at 15:00
3

Singleton is useful when you don't want multiple copies of a particular object, there must only be one instance of that class - it is used for objects that maintain global state, have to deal with non-reentrant code in some way etc.

A singleton that has a fixed number of 2 or more instances is a multiton, think of database connection pooling etc.

Interface specifies a well defined API that is helps model interaction between objects. In some cases, you could have a group of classes that do have some common functionality - if so, instead of duplicating it in implementations, you can add method definitions to the interface turning it into an abstract class.

You can even have an abstract class where all the methods are implemented, but you mark it as abstract to indicate it should not be used as-is without subclassing.

Note: Interface & abstract class aren't very different in the C++ world with multiple inheritance etc., but have different meanings in Java et al.

1
  • Very well said! +1
    – jmort253
    May 8, 2012 at 1:18
3

If you stop to think about it, its all about the polymorphism. You want to be able to write a piece of code once that can do more then one think depending on what you pass it.

Say we have a function like the following Python code:

function foo(objs):
    for obj in objs:
        obj.printToScreen()

class HappyWidget:
    def printToScreen(self):
        print "I am a happy widget"

class SadWidget:
    def printToScreen(self):
        print "I am a sad widget"

The good thing about this function is that it will be able to handle any list of objects, as long as those objects implement a "printToScreen" method. You can pass it a list of happy widgets, a list of sad widgets or even a list that has a mix of them and the foo function will still be able to correctly do its thing.

We refer to this type restriction of needing to have a set of methods implemented (in this case, printToScreen) as an interface and objects that implement all the methods are said to implement the interface.

If we were talking about a dynamic, duck-typed language like Python we would basicaly be over by now. However, C++'s static type system demands that we give a class to the objecs in our function and it will only be able to work with subclasses of that initial class.

void foo( Printable *objs[], int n){ //Please correctme if I messed up on the type signature
    for(int i=0; i<n; i++){
        objs[i]->printToScreen();
    }
}

In our case, the only reason the Printable class exists is to give a place for the printToScreen method to exist. Since there is no shared implementation between the classes that implement the printToScreen method, it makes sense to make Printable into an abstract class that is only used as a way to group similar classes in a common hierarchy.

In C++ the absctract class and interface concepts are a little bit blurry. If you want to define them better, abstract classes are what you are thinking about, while interfaces usualy mean the more general, cross-language idea of the set of visible methods an object exposes. (Although some languages, like Java, use the interface term to refer to something more directly like an abstract base class)

Basically, concrete classes specify how objects are implemented, while abstract classes specify how they interface with the rest of the code. To make your functions more polymorphi, you should try to receive a pointer to the abstract superclass whenever it would make sense to do so.


As for Singletons, they really are quite useless, since they can often be replaced by just a group of static methods or plain old functions. However, sometimes you have some sort of restriction that forces you to use an object, even though you wouldnt really want to use one, so the singleton patter is appropriate.


BTW, some people might have commented that the word "interface" has a particular meaning in the Java language. I think its better to stick with the more general definition for now though.

1

Interfaces

It's hard to understand the purpose of a tool that solves a problem that you've never had. I didn't understand interfaces for a while after I started programming. We'll I understood what they did, but I didn't know why you'd want to use one.

Here's the problem - you know what you want to do, but you have multiple ways to do it, or you may change how you do it later. It would be nice if you could play the role of the clueless manager - bark some orders and have the results you want without caring about how it's done.

Say you have a tiny little website, and you save all of your users' info in a csv file. Not the most sophisticated solution, but it works well enough to store your mom's user details. Later, your site takes off and you have 10,000 users. Maybe it's time to use a proper database.

If you were clever at first, you would have seen this coming and not made the calls to save to csv directly. Instead you'd think of what you needed it to do, no matter how it was implemented. Let's say store() and retrieve(). You make a Persister interface with abstract methods for store() and retrieve() and create a CsvPersister subclass that actually implements those methods.

Later, you can create a DbPersister that implements the actual storage and retrieval of data completely differently from how your csv class did it.

The great thing is, all you have to do now is change

Persister* prst = new CsvPersister();

to

Persister* prst = new DbPersister();

and then you're done. Your calls to prst.store() and prst.retrieve() will all still work, they're just handled differently "behind the scenes".

Now, you still had to create the cvs and db implementations, so you haven't experienced the luxury of being the boss yet. The real benefits are apparent when you're using interfaces that someone else created. If someone else was kind enough to create a CsvPersister() and DbPersister() already, then you just have to pick one and call the necessary methods. If you decide to use the other one later, or in another project, you already know how it works.

I'm really rusty on my C++, so I'll just use some generic programming examples. Containers are a great example of how interfaces make your life easier.

You can have Array, LinkedList, BinaryTree, etc. all subclasses of Container which has methods like insert(), find(), delete().

Now when adding something to the middle of a linked list, you don't even have to know what a linked list is. You just call myLinkedList->insert(4) and it magically iterates through the list and sticks it in there. Even if you know how a linked list works (which you really should), you don't have to look up its specific functions, because you probably already know what they are from using a different Container earlier.

Abstract Classes

Abstract classes are pretty similar to interfaces (well technically interfaces are abstract class, but here I mean base classes that have some of their methods fleshed out.

Say you're creating a game, and you need to detect when enemies are within striking distance of the player. You could create a base class Enemy that has a method inRange(). Although there are many things about the enemies that are different, the method used to check their range is consistent. Therefore your Enemy class will have a fleshed out method for checking range, but pure virtual methods for other things that share no similarities amongst the enemy types.

The nice thing about this is if you mess up the range detection code or want to tweak it, you only have to change it in one place.

Of course there are many other reasons for interfaces and abstract base classes, but those are some reasons why you might use them.

Singletons

I use them occasionally, and I've never been burned by them. That's not to say they won't ruin my life at some point, based on other peoples' experiences.

Here's a good discussion on global state from some more experienced and wary folks: Why is Global State so Evil?

1

In the animal kingdom there are various animals which are mammals. Here mammal is a base class and various animals derive from it.

Have you ever seen a mammal walking by? Yes, many times I am sure - however they were all types of mammal weren't they?

You have never seen something that was literally just a mammal. They were all types of mammal.

The class mammal is required to define various characteristics and groups but it does not exist as a physical entity.

Therefore it is an abstract base class.

How do mammals move? Do they walk, swim, fly etc?

There is no way to know at the mammal level but all mammals must move somehow (let us say that this is a biological law to make the example easier).

Therefore MoveAround() is a virtual function as every mammal who derives from this class needs to be able to implement it differently.

However, being as every mammal MUST define MoveAround because all mammals must move and it is impossible to do it at the mammal level. It must be implemented by all child classes but there it has no meaning in the base class.

Therefore MoveAround is a pure virtual function.

If you have an entire class that allows activity but is not able to define at the top level how it should be done then all of the functions are pure virtual and this is an interface.
For example - if we have a game where you will code a robot and submit it to me to fight in a battle ground I need to know the function names and prototypes to call. I do not care how you implement it on your side as long as the 'interface' is clear. Therefore I can provide you with an interface class which you will derive from to write your killer robot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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