One of my students make me a question (which answer i know) but I think could be instructive to formulate the same question here so many people can learn about it.
The question is:
How to implement a copy assignment into a Derived class?
Consider the following class A:

class A
{
public:
  A(int i1_) : i1{i1_} {}
  A(const A& a) : i1{a.i1} {} // Copy constructor
  A& operator=(const A& a)    // Copy assignment
    {
       i1=a.i1;
       return *this;
    }
private:
  int i1;
};

and you want to implement a derived class B:

class B: public A
{
public:
  B(int i1_, int i2_) : A{i1_}, i2{i2_} {}
  B(const B& b) : A{b}, i2{b.i2} {}   // Copy Constructor
  B& operator=(const B& b)            // Copy Assignment
    {
       /* HOW TO COPY b.i1 INTO i1 HERE? */
       i2=b.i2;
       return *this;
    }
private:
  int i2;
};

Note that in the copy constructor you can write : A(b) to copy b.i1 into the base.
Well, how you can make the same in de copy assignment?
Obviously you can not write i1=b.i1; because i1 is a private variable.

This is a question not for experimented but for medium and novice programmers to think and learn.
Enjoy!

Recommended Answers

All 8 Replies

Well, there are a number of problems with your code. Example, in the class B constructor, this

 B(int i1_, int i2_) : A{i1_}, i2{i2_} {}

should be this

 B(int i1_, int i2_) : A(i1_), i2(i2_) {}

Watch your parens vs brackets!

Interesting point.

I am using C++11. On C++11 you should use { } instead of ( ). This is called the universal initialization. It is not an error.
On C++03 and prior you must use ( ). On C++11 it is up to you to use the universal initialization { } or the old initialization ( ), however the former is recomended.

For this problem please forget this point between parentesis and brackets! The same problem can be formulated with parentesis.

B& operator=(const B& b)            // Copy Assignment
{
    if (&b != this) // you should always do this so you dont do a self assignment
    {
        A::operator=(b) // call A copy assignment
        i2=b.i2;
    }
    return *this;
}

@Maritimo
You could have simply commented about my lack of knowledge about C++11 in this regard (curly-braces vs parens) instead of a down-vote. The nice thing about "standards" is that there are so many! So, you get one also... :-(

P.S. Let's not let this degrade into a flame-war.

BTW, was there a real reason why the C++11 standard moved from parens to brackets? If so, can you tell me? Reply in private email if you prefer, or here if you wish to educate the rest of the community.

Rubberman: I chanched the down-vote. Sorry. Please don´t go into a war.

commented: I think we understand each other better now. All down-votes are removed, and thanks for the comments. I'm still new with C++11. +12

@rubberman - I think the main reason C++ added the brace initialization is that it now allows for more robust object initialization which enhances RAII. With brace initialization we can now write code like:

std::vector<int> numbers {1,2,3,4,5};

Instead of:

int array temp {1,2,3,4,5};
std::vector<int> numbers(temp, temp + 5);

Here are some addtional references for you:

http://en.cppreference.com/w/cpp/language/aggregate_initialization
http://en.cppreference.com/w/cpp/language/list_initialization

Nathan Oliver, you gave the write answer. My plan was to let some time for others to think about. But thank you. Also your correction about the self assignment is correct. I didn´t put it because I was waiting to be discovered. I am new here and I don´t know if you use to put some problems to solve and learn. I did this because I think it could be nice. Thanks.

So, you get one also... :-(

@rubberman: an eye for an eye? Not what I expected from you.

commented: Yeah. I removed my downvote. Maritimo and I are now on the same page. +12
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.