Java สำหรับการเขียนโปรแกรมภาษา C ++ กวดวิชากล่าวว่า (ไฮไลท์เป็นของตัวเอง):
สุดท้ายคำหลักคือประมาณ เทียบเท่ากับ const ใน C ++
"คร่าวๆ" หมายความว่าอะไรในบริบทนี้ พวกเขาไม่เหมือนกันหรือ
อะไรคือความแตกต่างถ้ามี?
Java สำหรับการเขียนโปรแกรมภาษา C ++ กวดวิชากล่าวว่า (ไฮไลท์เป็นของตัวเอง):
สุดท้ายคำหลักคือประมาณ เทียบเท่ากับ const ใน C ++
"คร่าวๆ" หมายความว่าอะไรในบริบทนี้ พวกเขาไม่เหมือนกันหรือ
อะไรคือความแตกต่างถ้ามี?
คำตอบ:
ในการทำเครื่องหมาย 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 ขั้นสุดท้ายสามารถใช้เพื่อทำเครื่องหมายสิ่งต่าง ๆ ว่าไม่สามารถ overridable C ++ (pre-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 อนุญาตให้ฟังก์ชันสมาชิกทำเครื่องหมายสุดท้ายให้ดูที่ส่วนอัพเดต 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
ในกรณีนี้ แต่เป็นการเพิ่มให้มันเป็นพฤติกรรมที่คล้ายกับจาวาที่ไม่เห็นด้วยคำสำคัญ C ++ ที่ใกล้เคียงที่สุด ดังนั้นหากคุณต้องการให้ฟังก์ชันสมาชิกเป็นทั้งสองอย่าง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 ++)
น่าสนใจเพื่อรักษาความเข้ากันได้ย้อนหลังกับรหัส pre-C ++ 11 final
ไม่ใช่คำหลักตามปกติ (นำตัวอย่าง C ++ 98 ที่น่าสนใจและถูกกฎหมายstruct final;
มาดูว่าทำไมการทำให้คำหลักใช้รหัสผิดพลาด)
final int a; a = 10; a = 11;
จะกล่าวถึงว่าไม่ใช่ (นั่นเป็นจุดประสงค์ของการfinal
เป็นตัวแปรปรับปรุง) นอกจากนี้สมาชิกสุดท้ายที่เรียนสามารถตั้งค่าได้ในเวลาที่ประกาศหรือครั้งเดียวในตัวสร้าง .
final
ตกแต่งฟังก์ชันสมาชิกเพื่อจุดประสงค์ที่แน่นอนนี้ VC ++ 2005 2008 และ 2010 ได้นี้ดำเนินการโดยใช้บริบทของคำหลักมากกว่าsealed
final
ใน Java คำหลักสุดท้ายสามารถใช้สำหรับสี่สิ่ง:
สิ่งหนึ่งที่สำคัญคือ: ตัวแปรสมาชิก Java สุดท้ายจะต้องตั้งค่าครั้งเดียว! ตัวอย่างเช่นใน Constructor, การประกาศฟิลด์หรือ Intializer (แต่คุณไม่สามารถตั้งค่าตัวแปรสมาชิกสุดท้ายในวิธีการ)
ผลที่ตามมาอีกประการหนึ่งของการทำให้ตัวแปรสมาชิกสุดท้ายเกี่ยวข้องกับโมเดลหน่วยความจำซึ่งมีความสำคัญหากคุณทำงานในสภาพแวดล้อมแบบเธรด
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
Java ขั้นสุดท้ายเทียบเท่ากับ C ++ const ในประเภทค่าดั้งเดิม
ด้วยประเภทการอ้างอิง Java คำหลักสุดท้ายจะเทียบเท่ากับตัวชี้ const ... เช่น
//java
final int finalInt = 5;
final MyObject finalReference = new MyObject();
//C++
const int constInt = 5;
MyObject * const constPointer = new MyObject();
คุณมีคำตอบที่ดีอยู่แล้วที่นี่ แต่จุดหนึ่งที่ดูเหมือนว่าควรจะเพิ่ม: const
ใน C ++ มักใช้เพื่อป้องกันส่วนอื่น ๆ ของโปรแกรมที่เปลี่ยนสถานะของวัตถุ ดังที่ได้อธิบายไว้final
ใน java ไม่สามารถทำเช่นนี้ได้ (ยกเว้นสำหรับ primitives) - เพียงแค่ป้องกันการอ้างอิงจากการเปลี่ยนเป็นวัตถุอื่น แต่ถ้าคุณใช้ a Collection
คุณสามารถป้องกันการเปลี่ยนแปลงวัตถุของคุณโดยใช้วิธีการคงที่
Collection.unmodifiableCollection( myCollection )
สิ่งนี้ส่งคืนการCollection
อ้างอิงที่ให้การเข้าถึงองค์ประกอบอ่าน แต่จะมีข้อผิดพลาดถ้าพยายามแก้ไขทำให้มันเหมือนกับconst
C ++
Java ใช้final
งานได้กับชนิดและการอ้างอิงดั้งเดิมเท่านั้นไม่ทำงานกับอินสแตนซ์ของวัตถุที่ตัวคำสั่ง const ทำงานกับสิ่งใด
เปรียบเทียบconst list<int> melist;
กับfinal List<Integer> melist;
รายการแรกทำให้ไม่สามารถแก้ไขรายการได้ในขณะที่รายการหลังหยุดคุณไม่ให้กำหนดรายการใหม่melist
เท่านั้น
นอกเหนือจากการมีคุณสมบัติมัลติเธรดที่แน่นอนและละเอียดอ่อนแล้วตัวแปรที่ประกาศfinal
ไม่จำเป็นต้องเริ่มต้นในการประกาศ!
เช่นนี้ถูกต้องใน Java:
// declare the variable
final int foo;
{
// do something...
// and then initialize the variable
foo = ...;
}
นี้จะไม่ถูกต้องถ้าเขียนด้วยภาษา C ++ const
's
ตามวิกิพีเดีย :
ฉันเดาว่ามันพูดว่า "คร่าว ๆ " เพราะความหมายของconst
ใน C ++ นั้นซับซ้อนขึ้นเมื่อคุณพูดถึงพอยน์เตอร์นั่นคือพอยน์เตอร์คงที่และพอยน์เตอร์ไปยังวัตถุคงที่ เนื่องจากไม่มีพอยน์เตอร์ "ชัดเจน" ใน Java final
จึงไม่มีปัญหาเหล่านี้
ให้ฉันอธิบายสิ่งที่ฉันเข้าใจด้วยตัวอย่างของคำสั่ง 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
เป็นตัวแปร class / instance และไม่ใช่ตัวแปรในตัวเครื่อง สิ่งนี้จะคอมไพล์หาก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 จึงไม่ได้ใช้