Soru C ++ iç içe geçmiş sınıf / ileri bildirim sorunu


İç içe geçmiş bir sınıfı ileriye bildirmek mümkün mü, daha sonra onu dış sınıfın veri üyesi için bir somut (işaretçi / referans değil) türü olarak kullanabilir mi?

I.E.

class Outer;

class Outer::MaybeThisWay   // Error: Outer is undefined
{
};

class Outer
{
 MaybeThisWay x;

 class MaybeThatOtherWay;

 MaybeThatOtherWay y;   // Error: MaybeThatOtherWay is undefined
};

32
2018-04-08 13:52


Menşei


Kodunuz "Dış Dış Dış Dış Dışını İçerir" içeriyor. - Muxecoid
olası kopyası İçsel bir sınıfı nasıl iletebilirim? - Aaron McDaid


Cevaplar:


İç içe geçmiş bir sınıfı böyle ilan edemezsiniz.

Ne yapmaya çalıştığınıza bağlı olarak, belki de dış katmandaki bir sınıf yerine bir ad alanı kullanabilirsiniz. Bu tür bir sınıfı sorunsuz bir şekilde bildirebilirsiniz:

namespace Outer {
   struct Inner; 
};

Outer::Inner* sweets;  // Outer::Inner is incomplete so 
                       // I can only make a pointer to it

Eğer Dış kesinlikle bir sınıf olmalı ve bir isim-alanına ayakkabılı olarak alamıyorsanız, o zaman İçsel'in beyan ettiğin bağlamda tam bir tür olması için Outer'e ihtiyacınız olacak.

class Outer
{
   class Inner;  // Inner forward-declared
};  // Outer is fully-defined now

Outer yes;  // Outer is complete, you can make instances of it
Outer::Inner* fun;  // Inner is incomplete, you can only make 
                    // pointers/references to it

class Outer::Inner 
{
};  // now Inner is fully-defined too

Outer::Inner win;  // Now I can make instances of Inner too

37
2018-04-08 14:25





İçerilen sınıfı tam olarak tanımlamaksızın iç içe geçmiş bir sınıf bildirmenin bir yolu yoktur. Bu küçük hile, sorunu çözer

class Outer_Inner
{
};

class Outer
{
public:
   typedef Outer_Inner Inner;
};

Bu benim adlandırma kuralımda olduğu gibi benim için çalışıyor Outer_Inner geçerli bir sınıf adı değil, dolayısıyla iç içe geçmiş bir sınıfa başvurduğu açıktır.

Yuvalanmış sınıfı şu şekilde beyan edemezsiniz:

class Outer::Inner;

Ancak en azından şu şekilde beyan edilebilir:

class Outer_Inner;

Outer_Inner'ın görünüşünü beğenmezseniz, zevkinize daha iyi uyan iç içe geçmiş sınıflar için bir adlandırma kuralı benimseyebilirsiniz. Outer__Inner, Outer_nested_Inner, vb.


15
2018-04-08 14:50



Çift alt çizgi kullanmayın - iki alt çizgi içeren isimler herhangi bir kullanım için uygulamaya ayrılmıştır. Görmek stackoverflow.com/questions/228783/... - villintehaspam
Burada karşılaştığım aynı sorun mu var? stackoverflow.com/questions/20214740/... - Julien Guertault


Hayır, ama neyin var?

class Outer {
public:  //or protected or private
    class Inner {
    };

private:
    Inner foo;
};

İleriye doğru beyan etmek, bir şeyleri kaçırmadığım sürece (ki bu sizin sorunuzun çok fazla ayrıntıda eksik olması gibi) mümkün olmadıkça anlam ifade etmiyor.

Unutmayın, eğer bir sınıf ileriye beyan edildiyse, o zaman sadece beyan edilen tipin bir nesnesine referanslar veya işaretçiler bildirebilirsiniz. Üyeleri veya işlevlerine erişmek de dahil olmak üzere başka hiçbir şey yapamazsınız.


1
2018-04-08 13:56



Inner, ileriye dönük olarak beyan edilmediğinden, burada tam olarak tanımlanmıştır. - CashCow
Ya bölümleri tersine çevireceksen. Belki genel bölümdeki bazı işlevler, özel değişkenler kullanır, dolayısıyla bunların bildirilmesi gerekir, ancak İçerde de özel olması gerekir. Inner'in şimdi özel bölümde görünmesine nasıl izin veriyoruz? - Sohaib


Eğer bir sınıf ileri bildirilmişse (ancak henüz tam tanımınız yoksa), sadece bir işaretçiyi ona bildirebilirsiniz, çünkü derleyici henüz sınıfın boyutunu bilmiyor (ya da alanlarının isimlerini bilmiyor) veya yöntemler).


1
2018-04-08 13:58





Türün bir özelliğini bildirirseniz MaybeThatOtherWaybir referans veya işaretçi değil, derleyicinin, dış sınıfın boyutunu belirlemek için sınıfın tam tanımını bilmesi gerekir. Dolayısıyla, ileriye dönük beyanı ve bu tür alan bildirimlerini, iç içe geçmiş bir sınıf olsun ya da olmasın, kullanamazsınız.


0
2018-04-08 14:05





Sadece bir işlev parametresi veya statik değişken olarak bir tür gerekirse, istemci tarafında yapılabilir. Örneğin, Outer'den etkinlik bildirimi almak için:

Arayüz:

class Client {
public:
private:
    static void gotIt(int event);
    class Helper;
};

Uygulama:

#include <outer.hpp>

class Client::Helper {
public:
    static void fromOuter(Outer::Inner const& inner) 
    { 
        gotIt(inner.event());
    }
};

0
2017-12-21 17:38