Akan mengganti '::' dengan '. dapat membuat ambiguitas dalam C ++?

95

Dalam C ++, operator ::digunakan untuk mengakses kelas, fungsi dan variabel dalam namespace atau kelas.

Jika spesifikasi bahasa yang digunakan .sebagai pengganti ::dalam kasus-kasus tersebut juga seperti ketika mengakses variabel instan / metode dari suatu objek, apakah itu akan menyebabkan kemungkinan ambiguitas yang tidak ada ::?

Mengingat bahwa C ++ tidak mengizinkan nama variabel yang juga merupakan nama jenis, saya tidak bisa memikirkan kasus di mana itu bisa terjadi.

Klarifikasi: Saya tidak bertanya mengapa ::dipilih ., hanya jika itu bisa bekerja juga?

Jimmy RT
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Samuel Liew

Jawaban:

124

Karena upaya untuk membuat C ++ sebagian besar kompatibel dengan kode C yang ada (yang memungkinkan collision nama antara nama objek dan tag struct), C ++ memungkinkan collision nama antara nama kelas dan nama objek.

Yang berarti:

struct data {
    static int member;
};

struct data2 {
    int member;
};

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

adalah kode yang sah.

Kit.
sumber
11
Jadi jawaban untuk pertanyaan dalam judul adalah Ya, tentu saja , bukan?
Enrico Maria De Angelis
2
@ EnricoMariaDeAngelis tidak sesederhana itu. Jika C ++ dikembangkan sebagai bahasa yang sama sekali baru, seperti Java atau C #, ambiguitas mungkin dapat dihindari . Tapi C ++ dikembangkan sebagai "C dengan kelas", dan itu sebabnya tidak. "Ya, itu akan " adalah jawaban yang benar, tetapi untuk pertanyaan yang berbeda.
Kit.
Tunggu, bukankah garis penugasan hanya menunjukkan bahwa menempatkan .atau di ::antara dua "kata" yang sama memiliki efek yang berbeda ( data.membermerujuk memberpada dataobjek kelas data2, sedangkan data::membermengacu memberpada kelas data)?
Enrico Maria De Angelis
1
Ya, tapi itu bukan sesuatu yang harus dibanggakan oleh perancang bahasa. Itu hanya sebuah artefak dari keputusan kompatibilitas.
Kit.
Ok, saya mengerti bahwa bagaimana C ++ hari ini dan sejauh ini (juga) tergantung pada apa C pada saat itu C ++ dikembangkan darinya. Tapi berbicara tentang C ++ apa adanya, dan mengesampingkan mengapa itu seperti apa adanya, akan ada ambiguitas jika semua ::diubah .. Di satu sisi Anda sudah menjawab ya . Saya tidak bisa menerobos komentar pertama Anda. Mungkin level saya membuat komentar itu terlihat berasap bagi saya.
Enrico Maria De Angelis
37

Contoh di mana keduanya valid, tetapi merujuk ke objek yang berbeda:

#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';
}

Lihat langsung di coliru .

Deduplicator
sumber
Dan yang ini tidak dapat dengan mudah diselesaikan dengan keputusan desain yang berbeda!
user253751
7

Ada perbedaan di antara keduanya a::b dan di a.bmana ::menyiratkan yang adigunakan sebagai namespace, yang berarti bahwa itu adalah namespace atau nama ketik. Asalkan C ++ mendukung pewarisan jamak non-virtual dan bahwa suatu variabel dapat memiliki nama yang sama dengan tipe, ini menghilangkan peluang referensi objek yang salah. Ini diperlukan untuk metaprogramming template.

Contoh lain adalah &B::foovs &B.foodalam konteks kelas B.

Swift - Friday Pie
sumber
2

Biarkan memperpanjang contoh @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.
}

Langsung di Coliru Viewer

Tidak memiliki kemungkinan untuk membedakan dengan bantuan ::, anggota mana yang ingin kita akses, tidak mungkin untuk mengakses anggota yang dinyatakan dalam kelas induk dengan nama yang identik.

SM
sumber
A A(nama variabel yang juga merupakan nama jenis) tidak valid dalam C ++, jadi contoh ini tidak berfungsi untuk saat ini
Jimmy RT
1
@ JimmyR.T. Ada contoh kehidupan kerja di Coliru Viewer. Konfirmasikan pernyataan Anda dengan paragraf dari standar.
SM
jika seseorang akan menambahkan berlian warisan terkutuk di sini dengan hal yang sama di sisi lain, itu akan menjadi puncak penamaan skizofrenia yang mungkin terjadi di C ++
Swift - Friday Pie