views:

543

answers:

6

Hi,

What do people here use C++ Abstract Base Class constructors for in the field? I am talking about pure interface classes having no data members and no non-pure virtual members.

Can anyone demonstrate any idioms which use ABC constructors in a useful way? Or is it just intrinsic to the nature of using ABCs to implement interfaces that they remain empty, inline and protected?

A: 

usually its solely to initialise members to sensible values.

gbjbaanb
Sometimes the ABC really does have a variable that can be initialized.
Joshua
+1  A: 

How could an abstract base class's constructor be used for anything?

Suppose you have an abstract base class B and a derived class D. When an object of type D is created, B's constructor is called first, but at that point, the object "is" still of type B (see here) -- in particular, calling any virtual functions from the body of B's constructor will call B's own implementations of those functions. But if B is a pure abstract class, none of those virtual functions are defined, so the program will crash immediately.

I'm guessing that you intended for B's constructor to call down to the most-derived-class's (e.g. D's) implementation of a virtual function, right? That would be a bad idea in general because D's object is not fully constructed yet, so any accesses to member variables in D from inside D's implementation of the virtual function would access uninitialised memory.

j_random_hacker
"I'm guessing that you intended for B's constructor to call down to the most-derived-class's (e.g. D's) implementation of a virtual function, right?"Nope, I know you can't do that, probably should have put that in my post.
You sure give the asker some credit... :)
xtofl
andrew: So do you mean ctors that do things with static members, like ChrisW's example? Since you explicitly said "no data members and no non-pure virtual members" your options are pretty limited...
j_random_hacker
+1  A: 

Remember: "Resource acquisition is initialization".

Sometimes we use abstract base classes as some kind of locking mechanism. For example, in a multi-threaded environment, where several threads need to share a single resource, then a thread can use the constructor as a way to acquire the resource, and the destructor to release the resource

void PlayWithPaintBallGun(Target &target)
{
    PaintBallGun paintBallGun;    // constructor waits until the gun is free,
                                  // then picks it up.

    paintBallGun.Aim(target);     // Shoot something
    paintBallGun.Fire();          //

                                  // Clever! The destructor is automatically
                                  // called when it goes out of scope. So we
                                  // can't forget to put the gun down.
}

Hugo

Rocketmagnet
This doesn't really answer my question. RAII classes themselves are not ABCs, although they can use them.
+3  A: 

Suppose that there is some behavior that is common for all the derived classes. Such as registering itself in some external registry, or checking validity of something.

All this common code can be placed in base class's constructor, and it will be called implicitly from the constructors of each of the derived classes.

Igor Oks
+5  A: 

Can anyone demonstrate any idioms which use ABC constructors in a useful way?

Here's an example, although it's a contrived, uncommon example.

You might use it to keep a list of all instances:

class IFoo
{
private:
  //static members to keep a list of all constructed instances
  typedef std::set<IFoo*> Set;
  static Set s_set;

protected:
  //new instance being created
  IFoo()
  {
    s_set.insert(this);
  }

public:
  //instance being destroyed
  virtual ~IFoo()
  {
    s_set.remove(this);
  }

  ... plus some other static method and/or property
      which accesses the set of all instances ...
};

Or is it just intrinsic to the nature of using ABCs to implement interfaces that they remain empty, inline and protected?

More usually they're just not declared at all! There's no reason to declare them:

  • Empty and inline => why bother to declare it?
  • Protected => the ABC probably already has some pure virtual methods and therefore already can't be instantiated except as a subclass.
ChrisW
Your example is basically of what I was thinking. Another idea that occurs to me is exploiting construction order in order to be able to safely call some siblings or members from lower down in the heirarchy, but I can't really think of a use for this.
Nice example ChrisW. Will +1 when I get some votejuice back.
j_random_hacker
+1  A: 

I can't think of many useful examples. A class without data-members has no state and thus can't initialize anything. You can have the constructor/destructor do logging for you, though. For example, to log the creation/destruction of all Visitor objects:

class Visitor {
public:
    Visitor() {
        std::cout << "Visitor@" << this << " created" 
                  << std::endl;
    }

    virtual ~Visitor() {
        std::cout << "Visitor@" << this << " destroyed" 
                  << std::endl;
    }

    virtual void visitA(A*) = 0;
    virtual void visitB(B*) = 0;
    // ...
};
Johannes Schaub - litb