Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Type non-static const member can't use default assignment operator' - what does this mean?

Tags:

c++

constants

This class is flagging up the following error: 'non-static const member 'const int Member::membershipNo', can't use default assignment operator'. The strange thing is this code is repeated in another project and works perfectly. Can you help me put it right?

Member.h

class Member : public Person
    {
    public:
        Member();
        Member(int membershipNo);
        virtual ~Member();

        int getMembershipNo() const;

    private:
        const int membershipNo;

        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive& ar, const unsigned int version)
        {
            ar & boost::serialization::base_object<Person>(*this);
            ar & membershipNo;
        }

    };

Member.cpp

Member::Member() : membershipNo(0)
{
    Person();
}

Member::Member(int memberNo) : membershipNo(memberNo)
{
    Person();
}

Member::~Member()
{
    // TODO Auto-generated destructor stub
}

int Member::getMembershipNo() const
{
    return membershipNo;
}
like image 982
Armada Avatar asked Feb 22 '13 18:02

Armada


2 Answers

Presumably, somewhere in your code you are assigning to a Member, something like this:

Member m1, m2;
m1 = m2;

Or you are using it in a context that requires the type to be assignable.

Since you don't provide your own assignment operator overload for Member, the implicitly defined defaulted assignment operator would usually kick in. However, since you have a const data member, the compiler won't implicitly define one for you. You need to provide it yourself.

This makes sense because, imagine in the code sample I just gave, what should the compiler do to m1's membershipNo member? Should it assign m2's membershipNo to it? How can it do that if membershipNo is const? In this case, the compiler just says "Nope, I can't do it."

A defaulted copy/move assignment operator for class X is defined as deleted if X has:

  • a non-static data member of const non-class type (or array thereof)
  • [...]

As I said, to be able to do assignment with a Member, you need to provide an assignment operator of your own:

Member& Member::operator=(const Member& other)
{
  // Copy things from other to this
}

However, herein lies the problem with having const members. If you supply your own copy assignment operator as described, and you don't copy over membershipNo, then have you really copied the other object? Logically, it makes sense that an object that has any const state shouldn't be able to be assigned to.

It is perfectly fine to use a copy constructor however - you only have to make sure you initialise membershipNo in the member initialization list:

Member::Member(const Member& other)
  : membershipNo(other.membershipNo)
{
  // ...
}

And then you can do:

Member m1;
Member m2 = m1;
like image 177
Joseph Mansfield Avatar answered Oct 20 '22 07:10

Joseph Mansfield


What is happening is that some client code is attempting to use assign one Member instance to another one. Since you have a constant data member, this cannot work. The error will only come up if some code attempts to make the assignment, which is why it may seem the same class "works" in another project.

In terms of putting it right, the options are A) not to perform the assignment, or B) make the data member non-const.

like image 45
juanchopanza Avatar answered Oct 20 '22 07:10

juanchopanza