if there's no derived class, why the example use the virtual? Does it have some advantage? |
The only reason to do it is to allow for the
possibility of a derived class to reimplement that function/operator. So if you wanted to make a derived class... you could do it without having to modify the base class.
I still can't understand this: |
'const correctness' is an optimization thing. Usage of 'const' objects tells the compiler "this object doesn't change", so it can take certain shortcuts in the code.
However, to make that "it doesn't change" promise, it imposes restrictions on the class.
1) class members cannot be modified. After all, if you're modifying them, you're breaking the promise:
1 2
|
const SomeClass object;
object.foo = 5; // illegal since 'object' is const. The compiler will error.
|
2) You can only call 'const' member functions with a const object. 'const' member functions impose the same restriction... they cannot modify the class members. Non-const functions have no restriction, therefore they cannot be called.
1 2 3 4 5
|
const SomeClass obj;
obj.AConstFunction(); // OK
obj.ANonConstFunction(); // compiler error, because the non-const function might modify
// the object, breaking the 'const' promise.
|
3) As an extension of #2, const functions cannot modify the object. Meaning they must also follow rules 1 and 2: They cannot modify member variables, nor can they call other non-const functions.
Your example:
1 2
|
T1 & first() {return a;}
T1 first()const {return a;}
|
Your example code is providing a const "read only" version of the 'first' function, which allows 'a' to be read when you have a const object.
It also overloads the 'first' function with a non-const version which allows 'a' to be
written, but only if the object is non-const. It allows writing by returning a reference to the 'a' variable (hence the & in the return type), rather than returning a copy of the 'a' variable (no & symbol).
Example usage:
1 2 3 4 5 6 7 8 9 10 11
|
SomeClass nc;
const SomeClass c;
// both objects can be used to read a:
x = nc.first(); // OK - calls non-const version, which assigns "x = a"
x = c.first(); // OK - calls const version which assigns "x = copy_of_a"
// but only the nc version can be used to write
nc.first() = 5; // OK - calls non-const version, which assigns "a = 5"
c.first() = 5; // Compiler error, the non-const version does not allow writing because
// it returns a value, not a reference.
|