I suppose this question needs an answer, given the other answers present.
You cannot apply final to variables in C++, so the question "which one is better" can only be answered with "const, because only this can compile".
final specifier was introduced to C++11 and can be applied:
- to classes, in this case class cannot be used as a base class
class A final {};
class B: public A {}; //error
- to
virtualfunction, to prevent derived classes from overriding it
class A {
virtual void foo() = 0;
};
class B: public A {
void foo() final {}
};
class C: public B {
void foo() {} //error
};
const keyword was in C++ since the very beginning and is used to
- mark variables as non-modifiable. Non-member variables must be initialized where they are declared, member must be initialized in constructor initializer list. It's not like
finalin Java, you cannot assign to it once.
const std::vector<int> v;
v = std::vector<int>{}; //error
v.push_back(1); //error
- to mark class member functions as usable with
constobjects. This also prevents you from modifying class members inside that function
class A {
int n;
public:
int getN() const {return n;}
void setN(int n) {this->n = n;} //cannot be const, modifies a member
};
const A a;
a.getN(); //fine
a.setN(5); //error
Answer from Yksisarvinen on Stack OverflowI suppose this question needs an answer, given the other answers present.
You cannot apply final to variables in C++, so the question "which one is better" can only be answered with "const, because only this can compile".
final specifier was introduced to C++11 and can be applied:
- to classes, in this case class cannot be used as a base class
class A final {};
class B: public A {}; //error
- to
virtualfunction, to prevent derived classes from overriding it
class A {
virtual void foo() = 0;
};
class B: public A {
void foo() final {}
};
class C: public B {
void foo() {} //error
};
const keyword was in C++ since the very beginning and is used to
- mark variables as non-modifiable. Non-member variables must be initialized where they are declared, member must be initialized in constructor initializer list. It's not like
finalin Java, you cannot assign to it once.
const std::vector<int> v;
v = std::vector<int>{}; //error
v.push_back(1); //error
- to mark class member functions as usable with
constobjects. This also prevents you from modifying class members inside that function
class A {
int n;
public:
int getN() const {return n;}
void setN(int n) {this->n = n;} //cannot be const, modifies a member
};
const A a;
a.getN(); //fine
a.setN(5); //error
No, that is not what final is used for. You might be confusing it with the use on other languages.
As you can see here, final is not used when declaring variables at all.
const int val = foo();
This is how you define a variable that will not be changed, which is the situation you mention in your question. final has nothing to do with it. This might be similar to what final means in some other languages, since foo() is not known at compile time and the variable needs to be initialized and then not changed afterwards. This is what const means in C++.
In C++, final is used to declare that a class will not be derived from, or a virtual function will not be further overridden.
Videos
In C++ marking a member function const means it may be called on const instances. Java does not have an equivalent to this. E.g.:
class Foo {
public:
void bar();
void foo() const;
};
void test(const Foo& i) {
i.foo(); //fine
i.bar(); //error
}
Values can be assigned, once, later in Java only e.g.:
public class Foo {
void bar() {
final int a;
a = 10;
}
}
is legal in Java, but not C++ whereas:
public class Foo {
void bar() {
final int a;
a = 10;
a = 11; // Not legal, even in Java: a has already been assigned a value.
}
}
In both Java and C++ member variables may be final/const respectively. These need to be given a value by the time an instance of the class is finished being constructed.
In Java they must be set before the constructor has finished, this can be achieved in one of two ways:
public class Foo {
private final int a;
private final int b = 11;
public Foo() {
a = 10;
}
}
In C++ you will need to use initialisation lists to give const members a value:
class Foo {
const int a;
public:
Foo() : a(10) {
// Assignment here with = would not be legal
}
};
In Java final can be used to mark things as non-overridable. C++ (pre-C++11) does not do this. E.g.:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
But in C++:
class Bar {
public:
virtual void foo() const {
}
};
class Error: public Bar {
public:
// Fine in C++
virtual void foo() const {
}
};
this is fine, because the semantics of marking a member function const are different. (You could also overload by only having the const on one of the member functions. (Note also that C++11 allows member functions to be marked final, see the C++11 update section)
C++11 update:
C++11 does in fact allow you to mark both classes and member functions as final, with identical semantics to the same feature in Java, for example in Java:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
Can now be exactly written in C++11 as:
class Bar {
public:
virtual void foo() final;
};
class Error : public Bar {
public:
virtual void foo() final;
};
I had to compile this example with a pre-release of G++ 4.7. Note that this does not replace const in this case, but rather augments it, providing the Java-like behaviour that wasn't seen with the closest equivalent C++ keyword. So if you wanted a member function to be both final and const you would do:
class Bar {
public:
virtual void foo() const final;
};
(The order of const and final here is required).
Previously there wasn't a direct equivalent of const member functions although making functions non-virtual would be a potential option albeit without causing an error at compile time.
Likewise the Java:
public final class Bar {
}
public class Error extends Bar {
}
becomes in C++11:
class Bar final {
};
class Error : public Bar {
};
(Previously private constructors was probably the closest you could get to this in C++)
Interestingly, in order to maintain backwards compatibility with pre-C++11 code final isn't a keyword in the usual way. (Take the trivial, legal C++98 example struct final; to see why making it a keyword would break code)
A const object can only call const methods, and is generally considered immutable.
const Person* person = myself;
person = otherPerson; //Valid... unless we declared it const Person* const!
person->setAge(20); //Invalid, assuming setAge isn't a const method (it shouldn't be)
A final object cannot be set to a new object, but it is not immutable - there is nothing stopping someone from calling any set methods.
final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!
Java has no inherent way of declaring objects immutable; you need to design the class as immutable yourself.
When the variable is a primitive type, final/const work the same.
const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages
There is a post on dart's website and it explains it pretty well.
Final:
"final" means single-assignment: a final variable or field must have an initializer. Once assigned a value, a final variable's value cannot be changed. final modifies variables.
Const:
"const" has a meaning that's a bit more complex and subtle in Dart. const modifies values. You can use it when creating collections, like const [1, 2, 3], and when constructing objects (instead of new) like const Point(2, 3). Here, const means that the object's entire deep state can be determined entirely at compile time and that the object will be frozen and completely immutable.
Const objects have a couple of interesting properties and restrictions:
They must be created from data that can be calculated at compile time. A const object does not have access to anything you would need to calculate at runtime. 1 + 2 is a valid const expression, but new DateTime.now() is not.
They are deeply, transitively immutable. If you have a final field containing a collection, that collection can still be mutable. If you have a const collection, everything in it must also be const, recursively.
They are canonicalized. This is sort of like string interning: for any given const value, a single const object will be created and re-used no matter how many times the const expression(s) are evaluated.
So, what does this mean?
Const:
If the value you have is computed at runtime (new DateTime.now(), for example), you can not use a const for it. However, if the value is known at compile time (const a = 1;), then you should use const over final. There are 2 other large differences between const and final. Firstly, if you're using const inside a class, you have to declare it as static const rather than just const. Secondly, if you have a const collection, everything inside of that is in const. If you have a final collection, everything inside of that is not final.
Final:
final should be used over const if you don't know the value at compile time, and it will be calculated/grabbed at runtime. If you want an HTTP response that can't be changed, if you want to get something from a database, or if you want to read from a local file, use final. Anything that isn't known at compile time should be final over const.
With all of that being said, both const and final cannot be reassigned, but fields in a final object, as long as they aren't const or final themselves, can be reassigned (unlike const).
Const
Value must be known at compile-time, const birthday = "2008/12/25"
Can't be changed after initialized.
Final
Value must be known at run-time, final birthday = getBirthDateFromDB()
Can't be changed after initialized.
First of all, since you referenced Java's final, that is a totally different beast than const. Final means the reference cannot change, but says nothing about mutability. Const goes further by saying "a const reference cannot mutate" which is a much stronger guarantee. To do this in Java, internal state must be final and determined at construction time. Const is a lot easier to use, and an existing object can be "promoted" into a const reference.
Yes, you should use const whenever possible. It makes a contract that your code will not change something. Remember, a non-const variable can be passed in to a function that accepts a const parameter. You can always add const, but not take it away (not without a const cast which is a really bad idea).
Const-correctness may be tedious at times, but it helps guarantee immutability. This is crucial in multi-threaded code where threads share objects. It makes certain tasks more efficient: instead of copying state, just reuse the same immutable object. Libraries might accept const parameters in order to provide a guarantee to the programmer that no, your object will not change in an unpredictable way in the black hole that is the library's guts.
Personally, const takes me very little time to write, and very little time to read, usually much less than it takes to check whether any code mutates the variable, and it actually prevents me from writing bugs (anyone ever incremented their end iterator by accident? Etc)
I also find that being strict about const usage guides me towards better code in other ways, like creating helper functions to do non-trivial initialization.