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?


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.


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 .


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.


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.


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.