İç sınıflar özel değişkenlere erişebilir mi?


117
class Outer {

    class Inner {
    public:
        Inner() {}
        void func() ;
    };

private:
    static const char* const MYCONST;
    int var;
};

void Outer::Inner::func() {
    var = 1;
}

const char* const Outer::MYCONST = "myconst";

Outer :: Inner 'sınıfıyla derlediğimde bu hata çıkıyor' var 'adlı bir üye yok

Yanıtlar:


120

İç sınıf, içinde tanımlandığı sınıfın bir arkadaşıdır.
Yani evet; tip bir amacı Outer::Innerüye değişkeni erişebilir vartip bir nesne Outer.

Java'nın aksine, türdeki Outer::Innerbir nesne ile ana sınıfın bir nesnesi arasında hiçbir ilişki yoktur . Ana çocuk ilişkisini manuel olarak yapmanız gerekir.

#include <string>
#include <iostream>

class Outer
{
    class Inner
    {
        public:
            Inner(Outer& x): parent(x) {}
            void func()
            {
                std::string a = "myconst1";
                std::cout << parent.var << std::endl;

                if (a == MYCONST)
                {   std::cout << "string same" << std::endl;
                }
                else
                {   std::cout << "string not same" << std::endl;
                }
            }
        private:
            Outer&  parent;
    };

    public:
        Outer()
            :i(*this)
            ,var(4)
        {}
        Outer(Outer& other)
            :i(other)
            ,var(22)
        {}
        void func()
        {
            i.func();
        }
    private:
        static const char* const MYCONST;
        Inner i;
        int var;
};

const char* const Outer::MYCONST = "myconst";

int main()
{

    Outer           o1;
    Outer           o2(o1);
    o1.func();
    o2.func();
}

14
Teknik olarak şu anki C ++ standardında, iç içe geçmiş bir sınıfın kapsayıcı sınıfına özel erişimi YOKTUR. Standardın 11.8.1 bölümüne bakın. ANCAK bu standart kusuru da görün: open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45
Greg Rogers

1
GCC, değeri ne olursa olsun, orada verilen önerilen çözümü izler, muhtemelen diğer derleyiciler de yapar.
Greg Rogers

24
C + 11 standardı artık yukarıdaki açıklama ile uyumludur.
Martin York

1
Java'da, statik olmayan iç sınıfa, iç sınıfa ilk erişildiğinde örtük olarak dış sınıfının örneğine bir başvuru (işaretçi) verilir. Bunu yeniden ifade etmek için jvm, @LokiAstari'nin cevabında bize gösterdiği şeye benzer şekilde sizin için dolaylı olarak bir kod yazıyor. İşte Effective Java 2nd Ed "Öğe 22: Statik üye sınıflarını statik olmayanlara tercih edin": "Bu değiştiriciyi (iç sınıfı bildirirken statik anahtar kelime) atlarsanız, her bir örnek, çevreleyen örneğine gereksiz bir referansa sahip olacaktır".
David Lee

3
@Loki Astari: Son cümleyi "Ebeveyn çocuk ilişkisini elle yapmanız gerekiyor" cümlesini okudum ve bunu doğru şekilde nasıl yapılacağına dair bir örnek olarak izleyen kod parçasını yorumladım !
Brent Baccala

32

Bir iç sınıfın dış sınıfın tüm üyelerine erişimi vardır, ancak bir üst sınıf örneğine örtük bir referansı yoktur (Java'daki bazı tuhaflıkların aksine). Dolayısıyla, dış sınıfa bir başvuru iç sınıfa iletirseniz, dış sınıf örneğindeki herhangi bir şeye başvurabilir.


7
bu c ++ 11'den itibaren geçerlidir
thrantir

6

Outer'un parçası olan her şey , herkese açık veya özel, Outer'ün tüm üyelerine erişebilmelidir.

Düzenleme: derleyiciniz doğru, var, Inner'ın bir üyesi değil. Ancak Outer örneğine bir referansınız veya işaretçiniz varsa, buna erişebilir.


2

var iç sınıfın bir üyesi değil.

Var'a erişmek için bir dış sınıf örneğine bir işaretçi veya başvuru kullanılmalıdır. Örneğin, pOuter-> var, eğer iç sınıf dış sınıfın bir arkadaşı ise veya, C ++ standardına kesinlikle uyuyorsa, var genel ise çalışacaktır.

Bazı derleyiciler iç sınıfları dışın dostu olarak ele alır, ancak bazıları olmayabilir. IBM derleyicisi için bu belgeye bakın :

"Yuvalanmış bir sınıf, başka bir sınıfın kapsamında bildirilir. İç içe geçmiş bir sınıfın adı, onu çevreleyen sınıf için yereldir. Açık işaretçiler, referanslar veya nesne adları kullanmadığınız sürece, iç içe geçmiş bir sınıftaki bildirimler yalnızca görünür yapıları kullanabilir; çevreleyen sınıftan ve genel değişkenlerden adları, statik üyeleri ve numaralandırıcıları yazın.

İç içe geçmiş bir sınıfın üye işlevleri, düzenli erişim kurallarını izler ve kendi kapsayıcı sınıflarının üyelerine özel erişim ayrıcalıklarına sahip değildir. Çevreleyen sınıfın üye işlevlerinin, iç içe geçmiş bir sınıfın üyelerine özel erişimi yoktur. "


4
Yanlış. Diğer cevapları görün - 3 yıl önce. "C ++ standardına sıkı sıkıya uyulursa" sizinkinden farklı yanıtlara ulaşır. C ++ 11 için erken bir taslaktan itibaren, yuvalanmış sınıflar, bir başvuru / işaretçi aracılığıyla üst öğenin tüm üyelerine erişebilir . Açıkça friendveya beyanına gerek yoktur public. IBM'in geçmişte ölü bir bağlantıda yanlış / modası geçmiş olması kimin umurunda? Bu yanıt, gönderilmeden 3 yıl önce zaten güncelliğini yitirmişti.
underscore_d

1

Öncelikle, varC ++ 'da izin verilmeyen sınıfın dışındaki statik olmayan üyeye erişmeye çalışıyorsunuz .

Mark'ın cevabı doğru.

Outer'un parçası olan her şey, herkese açık veya özel, Outer'ün tüm üyelerine erişebilmelidir.

Yani iki şey yapabilirsiniz, 'var'a erişmek için dış sınıfın bir örneğini varolarak bildirmek staticveya referansını kullanmak (çünkü bir arkadaş sınıfının veya işlevinin özel verilere erişmek için başvurması gerekir).

Statik değişken

Değişim variçin staticsize istemiyorsanız varsınıfın örnekleri ile ilişkili olduğu.

#include <iostream>

class Outer {

private:
    static const char* const MYCONST;
    static int var;

public:
   class Inner {
    public:
        Inner() {
          Outer::var = 1;
        }
        void func() ;
    };
};

int Outer::var = 0;

void Outer::Inner::func() {
    std::cout << "var: "<< Outer::var;
}

int main() {
  Outer outer;
  Outer::Inner inner;
  inner.func();

}

Çıktı-var: 1

Statik olmayan var

Bir nesnenin başvurusu, statik olmayan üye değişkenlere erişmelidir.

#include <iostream>

class Outer {

private:
    static const char* const MYCONST;
    int var;

public:
   class Inner {
    public:
        Inner(Outer &outer) {
          outer.var = 1;
        }
        void func(const Outer &outer) ;
    };
};

void Outer::Inner::func(const Outer &outer) {
    std::cout << "var: "<< outer.var;
}

int main() {
  Outer outer;
  Outer::Inner inner(outer);
  inner.func(outer);

}

Çıktı-var: 1

Düzenle - Harici bağlantılar Bloguma verilen bağlantılardır.

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.