No. I know you want int-like behavior for Register, and I agree now that this will improve the readability. Here is what I meant by implicit conversion:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
#include <iostream>
class Register {
private:
int qCurrent;
int qNext;
int getValue() const { return qCurrent; };
Register& setValue(int value)
{
qNext = value;
return *this;
}
public:
//explicit
Register(int cn = 0) : qCurrent(cn), qNext(cn) {}
Register& operator= (const Register& reg)
{
qNext = reg.qCurrent;
return *this;
}
operator int() const { return getValue(); }
// Register& operator= (int value) { return setValue(value); }
void print();
};
void Register::print()
{
std::cout << std::hex << "qCurrent: " << qCurrent << ". qNext: " << qNext << std::endl;
}
void f(Register arg)
{
arg.print();
}
int main(void)
{
Register x;
x.print(); //qCurrent: 0. qNext: 0
x = 1;
x.print(); //qCurrent: 0. qNext: 1
f(2); //qCurrent: 2. qNext: 2
}
|
First, I have underlined a change to your assignment operator's semantics. This is one of the things that I wanted to inquire in my previous post. I don't know if it's right, but it feels right. Second, I got the compound assignments out, because they are irrelevant for the demonstration.
This is what happens when you don't use the explicit keyword to mark the constructor. Despite that there is no implementation for assignment from int to Register in the above code (as I have commented it out), all runs fine. This is because int-s are converted to Register-s from the Register(int) constructor. In other words, the line
x = 1;
gets translated behind the scenes from the compiler into the line
x = Register(1);
. Your Register to Register assignment simply transfers the next state from the source and it is produced from the int.
This does save you from implementing the int to Register assignment. It may also save you from implementing the compound assignments (if you want them), if you implement compound Register to Register assignments instead.
Here is the warning though. If you opt for that route (which I prohibited in my previous posts by using the explicit keyword) and also change the logic of the Register to Register assignment in the future, so that it does not behave like an int assignment (as it does currently with my modifications in the above example), you have to remember to turn back to separate implementation of the int to Register and Register to Register assignments. Second, if you look at function f, you can see how implicit conversion from int to Register works and decide if you want those to be allowed implicitly. In general, it is a tad bit dangerous.
This has nothing to do with whether you allow the Register to behave like an int. The question is, whether you will allow int-s to be converted implicitly to Register-s. And save yourself the trouble of implementing several assignment operators at the cost of some possible vulnerability.
Again, as I told you in my previous post, the explicit keyword does nothing for you with constructors with two or more mandatory arguments. It doesn't do anything then, literally, so you could remove it from your code. You just don't have conversion constructors. But I wanted to show you how such constructors can help you, and hurt you, and to explain to you that you don't need the keyword with the two-argument constructor in your case.
Regard