Alex Rivera | Logout

Why does C++ not have a const constructor?

Asked 2011-08-04T04:20:29.207
45

(Edit: Heavy change because previous example was flawed, which may make some answers/comments seem odd)

This might be an overly contrived, but the following is legal because of lack of const constructor:

class Cheater
{
public:
    Cheater(int avalue) 
       : cheaterPtr(this) //conceptually odd legality in const Cheater ctor
       , value(avalue) 
    {}

    Cheater& getCheaterPtr() const {return *cheaterPtr;}
    int value;

private:
    Cheater * cheaterPtr;
};

int main()
{
    const Cheater cheater(7); //Initialize the value to 7

    cheater.value                 = 4;    //good, illegal
    cheater.getCheaterPtr().value = 4;    //oops, legal

    return 0;
}

It seems like providing a const constructor a thing would be as easy technically as const methods, and be analogous to a const overload.

Note: I'm not looking for 'Image( const Data & data ) const' but rather 'const Image( const Data & data) const'

So:

  • Why is the const constructor absent in C++?

Here's some related material for context:

Edit
Report

1 Answer

12

Just because Image is const in your imaginary constructor doesn't mean that what m_data points to is. You'd end up being able to assign a "pointer to const" to a "const pointer to non-const" inside your class, which would remove constness without a cast. This would obviously allow you to violate invariants and couldn't be allowed.

As far as I know, any specific sets of const-ness that are needed can be accurately and completely specified within the current standard.

Another way to look at it is that const means the method doesn't mutate your object's state. A constructor's sole purpose is to initialize an object's state to be valid (well hopefully anyway - any constructors with side effects should be ...carefully evaluated).

EDIT: In C++ constness applies to both members, and for pointers and references, to the accessible constness of the referred object. C++ consciously made the decision to split out these two different const-nesses. Firstly, do we agree that this code demonstrating the difference should compile and print out "non-const"?

#include <iostream>

struct Data
{
    void non_const() { std::cout << "non-const" << std::endl; }
};

struct Image
{
     Image(             Data & data ) : m_data( data ) {}

     void check() const { m_data.non_const(); }
     Data & m_data;
};

int main()
{
    Data data;
    const Image img(data);
    img.check();

    return 0;
}

So then in order to obtain the behavior where it could accept a const-ref and store it as const-ref, the effective declaration of the reference would have to change to be const. This would then mean that it would be a completely distinct type, NOT a const version of the original type (since two types with members differing in const-qualification are treated as two separate types in C++). Thus, either the compiler has to be able to do excessive behind

answered 2011-08-04T04:27:24.697

Your Answer