C ++ 'da bir sınıfın üyelerine başvurmak için ne zaman nokta, ok veya çift iki nokta üst üste kullanırım?


243

: C (Java veya C # gibi) diğer C-türevi dillere geliyor ++, ilk derece C ++ üç sınıfın üyeleri başvurmak için yollar vardır kafa karıştırıcı olan a::b, a.bve a->b. Bu operatörlerden hangisini ne zaman kullanırım?

(Not: Bu, Stack Overflow'ın C ++ SSS girişidir . Bu formda bir SSS sağlama fikrini eleştirmek istiyorsanız, tüm bunları başlatan metadaki yayınlama bunu yapmak için yer olacaktır. bu soru SSS fikrinin ilk başta başladığı C ++ sohbet odasında izlenir , bu nedenle cevabınızın bu fikri ortaya çıkaranlar tarafından okunması muhtemeldir.)

Yanıtlar:


248

C ++ 'ın bir sınıf veya sınıf nesnesinin üyelerine erişmek için kullandığı üç farklı işleç, yani çift kolon ::, nokta .ve ok ->, her zaman iyi tanımlanmış üç farklı senaryo için kullanılır. Bunu bilerek hemen ilgili oldukça çok şey biliyorum sağlar ave bsadece bakarak a::b, a.bya a->bsen bakmak herhangi bir kodda sırasıyla.

  1. a::byalnızca bsınıfın (veya ad alanının) bir üyesiyse kullanılır a. Yani, bu durumda aher zaman bir sınıfın (veya ad alanının) adı olacaktır.

  2. a.byalnızca bnesnenin bir üyesi (veya bir nesneye başvuru) ise kullanılır a. Bu nedenle a.b, aher zaman bir sınıfın gerçek bir nesnesi (veya bir nesneye başvuru) olacaktır.

  3. a->baslında, kısaca bir gösterimdir (*a).b. Bununla birlikte, ->aşırı yüklenebilen üye erişim operatörlerinden sadece bir tanesidir, bu nedenle aşırı yüklenen abir sınıfın nesnesi operator->(bu tür yaygın akıllı işaretçiler ve yineleyicilerdir), sınıf tasarımcısının uyguladığı her şey anlamdır. Sonuç olarak: ile a->b, abir işaretçi ise , işaretçinin başvurduğu bnesnenin bir üyesi olacaktır a. Bununla birlikte, abu operatörü aşırı yükleyen bir sınıfın nesnesi ise, aşırı yüklenmiş operatör işlevi operator->()çağrılır.


Küçük baskı:

  • C ++, türleri olarak ilan class, structya union"sınıfı türü" olarak kabul edilir. Yani yukarıdakilerin üçü de söz konusudur.
  • Referanslar, anlamsal olarak, nesneler için takma adlardır, bu yüzden # 3'e "veya bir işaretçiye başvuru" da eklemeliydim. Ancak, işaretçiler ( T*&) referansları nadiren kullanıldığından , bunun yararlı olmaktan daha kafa karıştırıcı olacağını düşündüm .
  • Nokta ve ok işleçleri, nesnenin üyesi olmasalar bile, bir nesnedeki statik sınıf üyelerine başvurmak için kullanılabilir. (Oli'ye bunu işaret ettiği için teşekkürler!)

10
Kesinlikle "nesnenin üyeleri" olmamasına rağmen, bir nesne aracılığıyla sınıf istatistiklerine erişmek için kullanılabileceği .ve ->kullanılabileceği de açıklığa kavuşturulmalıdır .
Oliver Charlesworth

@Oli: Bu gerçekten doğru. Küçük metne ekledim, çünkü ana metinde listelenecek kadar yaygın ve önemli olmadığını düşünüyorum.
sbi

3
Bütünlüğü sağlamak için, buna değer olduğuna dikkat işaret olabileceğini operator*()de aşırı edilebilir ve tutarlı olacak şekilde aşırı hiçbir şeyin kuvvetleri operator->()! (BTW'yi küçümsemedim, sadece uzun bir kopya dizisiyle buraya geldim)
juanchopanza

@OliCharlesworth bunun C ++ standardında nerede belirtildiğini biliyor musunuz?
domuz

1
@juanchopanza: Ancak ->aşırı yüklenerek operator*ve kullanarak zincirleme davranışını elde edemezsiniz .. operator->Bunu sadece aşırı yükler alır.
Ben Voigt

36

Sami'nin 3. noktası için bir alternatif önermek

a->byalnızca abir işaretçi ise kullanılır . Bu bir kısaltmadır (*a).b, bo nesnenin üyesi aişaret ettiği. C ++, "normal" ve akıllı işaretçiler olmak üzere iki tür işaretçi içerir. Gibi düzenli işaretçiler için A* a, derleyici uygular ->. Gibi akıllı işaretçi için std::shared_ptr<A> a, ->sınıfın bir üyesi fonksiyonudur shared_ptr.

Gerekçe: Bu SSS'nin hedef kitlesi akıllı işaretçiler yazmıyor. Bilmelerine gerek yok ->, gerçekten denir operator->()veya aşırı yüklenebilen tek üye erişim yöntemidir.


4
Kabul edersem de etmesem de, bunu +1sadece alternatif bir cevap vermek için veririm .
sbi

2
Adil olmak ->, herhangi bir C ++ programcısının yakında karşılaması gereken standart yineleyiciler için aşırı yüklenmiştir, bu yüzden sadece işaretçiler için kullanıldığını söylemek kafa karıştırıcı olabilir.
Kiscsirke

@Kiscsirke "sıradan C ++ programcıları" sadece bunları kullanarak akıllı işaretçi veya yineleyici türleri yazmak zorunda değilsiniz . "İşaretçi gibi dereferences" her ikisi için de geçerlidir.
Caleth

0
#include <iostream>
#include <string>

using namespace std;

class Human {
private:
    int age;

public:
    string name;

    Human(int humanAge, string humanName) 
         : age(humanAge), name(std::move(humanName)) {}

    void DoSomething() {
        cout << age << endl;
    }

    static void DisplayAge(const Human& person) {
        cout << person.age << endl;
    }

    // ...
};

int main() {
    // Usage of Dot(.) 
    Human firstMan(13, "Jim"); // firstMan is an instance of class Human
    cout << firstMan.name << endl; // accessing member attributes
    firstMan.DoSomething(); // accessing member functions

    // Usage of Pointer Operator (->)
    Human* secondMan = new Human(24, "Tom");
    cout << secondMan->name << endl; // accessing member attributes
    secondMan->DoSomething(); // accessing member functions
    cout << (*secondMan).name << endl; // accessing member attributes
    (*secondMan).DoSomething(); // accessing member functions

    // Usage of Double Colon (::)
    Human::DisplayAge(firstMan);
    firstMan.DisplayAge(firstMan); // ok but not recommended
    secondMan->DisplayAge(firstMan); // ok but not recommended

    delete(secondMan);

    return 0;
}

Yukarıdaki kodlama Örneğin, görebiliriz o:
* nokta işleci (örneğine (veya nesneyi) üyeleri (özellikleri ve işlevleri) Erişme .)
Bir nesneye işaretçi üyeleri (özellikleri ve işlevleri) Erişme * (ya da yarattığı new) pointer operatörünü kullanarak ( ->)
* Çift kolon ( ::) kullanarak bir nesne olarak bir nesneye sahip olmadan statik üye işlevlerine sınıfın kendisinden erişme . [ Not: statik üye işlevini tavsiye edilmeyen .veya ->önerilmeyen bir örnekten de çağırabilirsiniz ]


@sbi çok huysuz ha, bunun bir tür tekrar olduğunu biliyorum. Bunların nasıl kullanılacağını göstermek için açık bir örnek vermek istiyorum. Ve nerede dedim ->sadece yığın tarafından tahsis bir işaretçi tarafından kullanılabilir new? Aşağıda, ikinci madde, sanırım gerçekten ->işaretçi için netleştirmek . Ve indirmeden önce, className::non_static_member_function()c ++ 14 ile kendiniz denemeniz daha iyi . Referans bir işaretçi değildir, bu yüzden kullanabilir .ve cevabımda daha net hale getireceğim.
Hu Xixi

0

Nokta operatörü doğrudan üye seçim senaryolarında kullanılır.

print(a.b)

Burada, bbir nesnenin doğrudan üyesi olan erişime erişiyoruz a. Yani, öncelikle, abir nesnedir ve b(fonksiyon / değişken vb a.)


Dolaylı üye seçim senaryolarında ok operatörü kullanılır .

print(a->b)

Burada, bnesnenin bir üyesi olan ve işaret ettiği noktaya erişiyoruz a. Bu kestirme (*a).bve dolayısıyla burada, aöncelikle bir nesnenin göstergesidir ve bo nesnenin bir üyesidir.


Double Colon (Scope) operatörü, ad alanı ile ilgili doğrudan üye seçim senaryolarında kullanılır.

print(a::b)

Burada, bsınıfın / ad alanının bir üyesi olan erişime erişiyoruz. Bu nedenle aöncelikle abir sınıf / ad alanı ve bbir üyesi (işlev / değişken vb a.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.