tags:

views:

369

answers:

7

Is a public constructor in an abstract class a codesmell? Making the constructor protected provides all of the access of which you could make any use. The only additional access that making it public would provide would be to allow instances of the class to be declared as variables in scopes that cannot access its protected members, but instances of abstract classes cannot be declared at all.

+3  A: 

As you say, there is no need to provide public constructor of abstract class, nor it can be misused, if you provide public constructor.

However, you may consider declaring constructor as public as recomendation for structuring classes derived from the abstract one.

Burgos
Can you explain your second sentence? I don't understand what the recommendation might be.
quamrana
I think public ctors will recommend implementing classes a means of designing the public interface. Like, an abstract "Window" class could have a public ctor that has a parameter "Window *parent". It will recommend deriving classes to provide it as a public constructor too, which will be part of the interface.
Johannes Schaub - litb
I thought that might be the case - I'd say that its wrong. I would say that in the case of a ctor, it should be protected and take the parameters it needs, quite independently of what derived classes should do. Any other public pure virtual member functions, however, **should** be a strong indication that a leaf class needs to implement these with (obviously) the same access level and parameters.
quamrana
+10  A: 

I've read it in at least one coding guideline that constructors of abstract classes should not be public - I think that rule makes sense for the reason you gave.

However, i can't imagine a scenario where making it public would make things go wrong. So i wouldn't go so far as saying it's a code smell. I see the protected constructor as a "nice to have" property :)

Johannes Schaub - litb
Agree, the protected constructor explicits the fact that the class cannot be directly instantiated, so it is a "nice property" from the programmer point of view, even if the compiler does not really care about it.
David Rodríguez - dribeas
Coding guidelines are supposed to protect you from bad things that could happen. As you can not instanciate an abstract class I don't see what this guideline is protecting you from and thus feels arbitory.
Martin York
They say by making it protected, you make it explicit that it cannot be used by derived classes. I suspect that it's a similar rationale as with member operator new and delete: They are implicitly static members, but it's good to make them explicitly static. On the other side, in-class definition of member functions are implicitly inline, and i would say it's poor to make them explicitly inline. In the end, i think this protected-constructor issue is rather a matter of taste.
Johannes Schaub - litb
+2  A: 

My opinion would be that the public constructor might be seen to be confusing, and as you say making it protected would be correct. I would say that a protected constructor correctly reinforces the impression that the only sensible use of an abstract class is to derive from it.

In fact, you only need to declare a constructor in an abstract class if it needs to do something, eg. initialise its own private members. I would then expect there to be other protected member functions that are helpful to derived classes.

EDIT:

Since no-one has posted any code and @sbi asked for some in a comment to OP, I thought I would post some:

class Base:
{
public:           // The question is: should the ctor be public or protected?
// protected:
    Base():i(0){} // ctor is necessary to initialise private member variable
public:
    virtual ~Base(){} // dtor is virtual (but thats another story)
                  // pure virtual method renders the whole class abstract
    virtual void setValue(void)=0;  
protected:
    int getValue(void){ return i;}
private:
    int i;
};

Base b1;  // Illegal since Base is abstract, even if ctor is public
Base& b2=makeBase();  //We can point to, or refer to a Base
b2.setValue();    // We're not sure what this does, but we can call it.
b2.getValue();    // Illegal since getValue is protected
quamrana
A: 

Be careful though to explicitly declare/define your protected/private copy constructor. If you don't the compiler will do it for you. See scott meyers effective c++ item 6.

count0
Don't you mean destuctor instead of constructor? What's bad about a default generated constructor?
TimW
You're right. Sorry, i meant copy constructor, else the whole thing doesn't make sense.
count0
A: 

I'd say its a bad sign for a couple of reasons.

The first is that it might mislead somebody into thinking they can actually call that routine.

The second is that it implies the author thought you could call it. You now don't know if that was an important part of his design or not.

T.E.D.
I don't think those are valid arguments. No one who knows the first thing about OO design or C++ would think that you could call it and second of all the compiler will give an error the moment you try.
Robert S. Barnes
+2  A: 

I know that allot of people obviously disagree, but I don't think an abstract classes ctor should be protected unless the interface you are designing has a specific reason for all derived classes to also have a protected ctor.

The reason is that when you design an abstract class you're designing an interface to be implemented by the deriving classes. Derived classes should implement the interface exactly as it's designed in the base class. The interface presented by an abstract base class is a contract; don't break that contract.

Or in other words, if you're changing the interface, why are you deriving from that class in the first place?

This is a bit of a religious answer, but what the heck. ;-)

Robert S. Barnes
@Robert: I understand your reason given here, but I believe that it does not apply to the ctor. Yes, other public and protected member functions (excluding the ctor and dtor) provide interfaces that are a contract and you should think twice before changing them.
quamrana
+3  A: 

Abstract class can never be directly instantiated because of the pure virtual methods it declares. So, declaring constructor as protected is just adds additional tips for programmers.

I saw recommendation to declare constructor as protected here, in Google style guide. And I've met similar recommendations in some other corporate coding standards. So this is looks like a good practice.

Kirill V. Lyadvinsky