จะแทนที่ '::' ด้วย ' สร้างความคลุมเครือใน C ++ หรือไม่


95

ใน C ++ ตัวดำเนินการ::ถูกใช้เพื่อเข้าถึงคลาสฟังก์ชันและตัวแปรในเนมสเปซหรือคลาส

หากข้อกำหนดทางภาษาที่ใช้.แทน::ในกรณีเหล่านั้นเช่นกันเช่นเมื่อเข้าถึงตัวแปร / วิธีการของวัตถุแล้วจะทำให้เกิดความคลุมเครือที่อาจเกิดขึ้นซึ่งไม่ได้มีอยู่ด้วย::หรือไม่?

เนื่องจาก C ++ ไม่อนุญาตให้ใช้ชื่อตัวแปรที่เป็นชื่อประเภทด้วยฉันไม่สามารถนึกถึงกรณีที่อาจเกิดขึ้นได้

ชี้แจง: ฉันไม่ได้ถามว่าทำไมถึง::เลือก.แม้ว่ามันจะทำงานได้เช่นกัน?


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Samuel Liew

คำตอบ:


124

เนื่องจากความพยายามที่จะทำให้ C ++ ส่วนใหญ่เข้ากันได้กับรหัส C ที่มีอยู่ (ซึ่งช่วยให้การชนชื่อระหว่างชื่อวัตถุและแท็ก struct), C ++ ช่วยให้การชนชื่อระหว่างชื่อคลาสและชื่อวัตถุ

ซึ่งหมายความว่า:

struct data {
    static int member;
};

struct data2 {
    int member;
};

void f(data2& data) {
    data.member = data::member;
}

เป็นรหัสที่ถูกต้อง


11
ดังนั้นคำตอบของคำถามในหัวข้อคือใช่มันจะใช่ไหม
Enrico Maria De Angelis

2
@EnricoMariaDeAngelis มันไม่ง่ายเลย C ++ ได้รับการพัฒนาเป็นภาษาใหม่อย่างสมบูรณ์เช่น Java หรือ C # ความคลุมเครืออาจหลีกเลี่ยงได้ แต่ C ++ ได้รับการพัฒนาเป็น "C กับคลาส" และนั่นคือสาเหตุที่ไม่ใช่ "ใช่มันจะ " เป็นคำตอบที่ถูกต้อง แต่สำหรับคำถามอื่น
ชุด

รอไม่ได้เป็นสายที่ได้รับมอบหมายเพียงแค่แสดงให้เห็นว่าการวาง.หรือ::ระหว่างเดียวกันสอง "คำว่า" มีผลกระทบที่แตกต่างกัน ( data.memberหมายถึงmemberของdataวัตถุของคลาสdata2ในขณะที่data::memberหมายถึงmemberการเรียนdata)
Enrico Maria De Angelis

1
ใช่ แต่ไม่ใช่สิ่งที่นักออกแบบภาษาควรภูมิใจ มันเป็นเพียงส่วนหนึ่งของการตัดสินใจที่เข้ากันได้
ชุด

โอเคฉันเข้าใจว่า C ++ เป็นอย่างไรในปัจจุบันและตอนนี้ (เช่น) ขึ้นอยู่กับว่า C คืออะไรในเวลาที่ C ++ พัฒนาขึ้นจากมัน แต่การพูดคุยของ C ++ มันเป็นและออกจากกันทำไมมันเป็นอย่างที่มันเป็นจะมีความคลุมเครือถ้าทุกอย่างเปลี่ยนแปลงไป:: .ในแบบที่คุณตอบว่าใช่แล้ว ฉันไม่สามารถละเมิดความคิดเห็นแรกของคุณได้ บางทีระดับของฉันอาจทำให้ความคิดเห็นนั้นดูไร้ควันสำหรับฉัน
Enrico Maria De Angelis

37

ตัวอย่างที่ทั้งคู่ใช้งานได้ แต่อ้างอิงถึงออบเจกต์ต่าง ๆ :

#include <iostream>

struct A {
    int i;
};

struct B {
    int i;
    A B;
};

int main() {
    B x {0, 1};
    std::cout << x.B.i << '\n';
    std::cout << x.B::i << '\n';
}

ดูสดบน coliru


และอันนี้ไม่สามารถแก้ไขได้อย่างง่ายดายด้วยการตัดสินใจออกแบบที่แตกต่างกัน!
user253751

7

มีความแตกต่างระหว่างa::bและa.bตำแหน่งที่::บอกเป็นนัยซึ่งaใช้เป็นเนมสเปซซึ่งหมายความว่าเป็นเนมสเปซหรือพิมพ์ดีด โดยมีเงื่อนไขว่า C ++ รองรับการสืบทอดพหูพจน์ที่ไม่ใช่เสมือนจริงและตัวแปรสามารถมีชื่อเดียวกับประเภทได้ซึ่งจะช่วยลดโอกาสในการอ้างอิงวัตถุที่ผิด จำเป็นสำหรับเทมเพลตการวางแผนโปรแกรม

อีกตัวอย่างหนึ่งคือ&B::foovs &B.fooในบริบทของคลาส B


2

ให้ขยายตัวอย่าง @Deduplicator:

#include <iostream>

struct A {
    int i;
};

struct B : public A {
    int i;
    A A;
};

int main() {
    B x {1, 2};
    std::cout << x.i << '\n';
    std::cout << x.B::i << '\n';  // The same as the line above.
    std::cout << x.A.i << '\n';
    std::cout << x.A::i << '\n';  // Not the same as the line above.
}

ถ่ายทอดสดบน Coliru Viewer

ไม่มีความเป็นไปได้ที่จะแยกแยะด้วยความช่วยเหลือของ :: สมาชิกคนไหนที่เราต้องการเข้าถึงมันเป็นไปไม่ได้ที่จะเข้าถึงสมาชิกที่ประกาศในคลาสแม่ที่มีชื่อเหมือนกัน


A A(ชื่อตัวแปรที่เป็นชื่อประเภทด้วย) ไม่ถูกต้องในภาษา C ++ ดังนั้นตัวอย่างนี้ใช้ไม่ได้ตอนนี้
Jimmy RT

1
@ JimmyR.T มีตัวอย่างชีวิตการทำงานบน Coliru Viewer ยืนยันข้อความของคุณด้วยย่อหน้าจากมาตรฐาน
SM

ถ้าใครจะเพิ่มเพชรมรดกที่ถูกสาปที่นี่ด้วยสิ่งเดียวกันในอีกด้านหนึ่งมันจะเป็นจุดสุดยอดของการตั้งชื่อโรคจิตเภทที่เป็นไปได้ใน C ++
Swift - Friday Pie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.