Answers:
在C ++中,标记成员函数const
意味着可以在const
实例上调用它。Java没有与此等效的功能。例如:
class Foo {
public:
void bar();
void foo() const;
};
void test(const Foo& i) {
i.foo(); //fine
i.bar(); //error
}
只能在Java中一次分配值,例如:
public class Foo {
void bar() {
final int a;
a = 10;
}
}
在Java中合法,但在C ++中不合法,而:
public class Foo {
void bar() {
final int a;
a = 10;
a = 11; // Not legal, even in Java: a has already been assigned a value.
}
}
在Java和C ++中,成员变量都可以分别为final
/ const
。在类的实例完成构造时,需要为它们提供一个值。
在Java中,必须在构造函数完成之前对其进行设置,这可以通过以下两种方法之一来实现:
public class Foo {
private final int a;
private final int b = 11;
public Foo() {
a = 10;
}
}
在C ++中,您将需要使用初始化列表为const
成员赋予一个值:
class Foo {
const int a;
public:
Foo() : a(10) {
// Assignment here with = would not be legal
}
};
在Java中,final可用于将事物标记为不可覆盖。C ++(C ++ 11之前的版本)不执行此操作。例如:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
但是在C ++中:
class Bar {
public:
virtual void foo() const {
}
};
class Error: public Bar {
public:
// Fine in C++
virtual void foo() const {
}
};
这很好,因为标记成员函数的语义const
是不同的。(您也可以仅通过启用一个成员函数来重载const
。(另请注意,C ++ 11允许将成员函数标记为final,请参阅C ++ 11更新部分)
实际上,C ++ 11确实允许您将类和成员函数都标记为final
,具有与Java中相同功能(例如Java)相同的语义:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
现在可以完全用C ++ 11编写为:
class Bar {
public:
virtual void foo() final;
};
class Error : public Bar {
public:
virtual void foo() final;
};
我必须使用G ++ 4.7的预发行版来编译此示例。请注意,const
在这种情况下,它不会替代,而是对其进行了增强,提供了与Java最为相似的C ++关键字所看不到的类似于Java的行为。因此,如果您希望成员函数兼而有之final
,则const
可以执行以下操作:
class Bar {
public:
virtual void foo() const final;
};
(顺序const
和final
位置是必需的)。
以前并没有const
成员函数的直接等效项,尽管将函数virtual
设为非- 是一个潜在的选择,尽管不会在编译时引起错误。
同样,Java:
public final class Bar {
}
public class Error extends Bar {
}
变成C ++ 11:
class Bar final {
};
class Error : public Bar {
};
(以前,private
构造函数可能是您在C ++中最接近的构造函数)
有趣的是,为了保持与C ++ 11以前的代码的向后兼容性,通常final
不是关键字。(以简单,合法的C ++ 98示例为例struct final;
,为什么将其设为关键字会破坏代码)
final int a; a = 10; a = 11;
是(这是final
作为变量修饰符的目的。)此外,类的最终成员只能在声明时或在构造函数中设置一次。 。
final
为此目的添加了成员函数装饰器。VC ++ 2005、2008和2010已经使用上下文关键字sealed
而不是来实现了final
。
在Java中,final关键字可用于四件事:
重要的一点是:Java的final成员变量必须设置一次!例如,在构造函数,字段声明或初始化器中。(但是您不能在方法中设置最终成员变量)。
使成员变量成为final的另一个结果与内存模型有关,如果您在线程环境中工作,这很重要。
一个const
对象只能调用const
方法,并且通常被认为是不可变的。
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)
一个final
对象不能设置为一个新对象,但是它不是不可变的-没有什么可以阻止某人调用任何set
方法。
final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!
Java没有固有的声明对象不变的方法。您需要自己将类设计为不可变的。
当变量是原始类型时,final
/的const
工作方式相同。
const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages
您已经在这里有了一些不错的答案,但是似乎有一点值得补充:const
C ++通常用于防止程序的其他部分更改对象的状态。正如已经指出的那样,final
在Java中不能做到这一点(除了基元),它只是防止将引用更改为其他对象。但是,如果您使用Collection
,则可以使用静态方法防止更改对象
Collection.unmodifiableCollection( myCollection )
这将返回一个Collection
对元素进行读取访问的引用,但是如果尝试进行修改,则将引发异常,使其有点像const
C ++
让我用switch / case语句示例解释我的理解。
每个case语句中的值必须是与开关值相同的数据类型的编译时常量值。
声明以下内容(在方法中作为本地实例,或在类中作为静态变量(然后向其添加静态),或实例变量。
final String color1 = "Red";
和
static final String color2 = "Green";
switch (myColor) { // myColor is of data type String
case color1:
//do something here with Red
break;
case color2:
//do something with Green
break;
}
如果color1
是类/实例变量而不是局部变量,则此代码将不会编译。如果color1
定义为静态最终变量,则将进行编译(然后它将变为静态最终变量)。
当不编译时,会出现以下错误
error: constant string expression required
关键字“ const”表示您的变量保存在ROM(带有微处理器)中。在计算机中,您的变量将保存在RAM区中,用于汇编代码(只读RAM)。这意味着您的变量不在可写RAM中,包括:静态内存,堆栈内存和堆内存。
关键字“ final”表示您的变量保存在可写RAM中,但是您会向编译器注意到,您的变量仅更改了一次。
//in java language you can use:
static final int i =10;
i =11; //error is showed here by compiler
//the same in C++ the same as follows
int i =10;
const int &iFinal = i;
iFinal = 11; //error is showed here by compiler the same as above
我认为“ const”的性能不好,因此Java不使用它。