Java的最终vs.C++的康斯特

2022-08-31 07:20:08

Java for C++程序员教程说(突出显示是我自己的):

关键字 final 大致相当于 C++

在这种情况下,“大致”是什么意思?它们不是完全相同吗?

如果有的话,有什么区别?


答案 1

在C++标记成员函数意味着可以在实例上调用它。Java 没有与此等效的。例如:constconst

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++成员变量可以分别是/。在类的实例完成构造时,需要为它们赋值。finalconst

在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 {
   }
};

这很好,因为标记成员函数的语义是不同的。(您也可以通过仅具有 on 其中一个成员函数来重载。(另请注意,C++11 允许将成员函数标记为最终状态,请参阅C++11 更新部分)constconst


C++11更新:

C++11 实际上允许您将类和成员函数标记为 ,在 Java 中具有与相同功能相同的语义,例如在 Java 中:final

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的预发布来编译这个例子。请注意,在这种情况下,这不会替换它,而是增强它,提供类似Java的行为,而最接近的等效C++关键字则看不到这些行为。因此,如果您希望成员函数同时具有两者,并且您会这样做:constfinalconst

class Bar {
public:
  virtual void foo() const final;
};

(此处的顺序为必填项)。constfinal

以前没有成员函数的直接等价物,尽管使函数成为非-将是一个潜在的选择,尽管在编译时不会导致错误。constvirtual

同样,Java:

public final class Bar {
}

public class Error extends Bar {
}

在C++11中变成:

class Bar final {
};

class Error : public Bar {
};

(以前构造函数可能是您在C++中最接近这一点的构造函数)private

有趣的是,为了保持与预C++11代码的向后兼容性不是通常方式的关键字。(以一个微不足道的、合法的C++98为例,看看为什么把它作为一个关键字会破坏代码)finalstruct final;


答案 2

对象只能调用方法,并且通常被认为是不可变的。constconst

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)

对象不能设置为新对象,但它不是不可变的 - 没有什么可以阻止某人调用任何方法。finalset

final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!

Java没有固有的方法来声明对象不可变;您需要自己将类设计为不可变的。

当变量是基元类型时,/工作方式相同。finalconst

const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages

推荐