Newsgroup: it.comp.lang.c++
Titolo: Derivazione di classe annidata

Ragazzi guardate questo codice:
class A {
        class nestedclass {...};
}
class B : public A {
        class nestedclass2 : public A::nestedclass {...}
}
Questa forma di derivazione non mi va bene, perché io voglio che i 
riferimenti a nestedclass che si trovano in A, nella classe B si rivolgano 
a nestedclass2.
Qualche consiglio???


Cosa vuoi dire con: "voglio che i  riferimenti a nestedclass che si trovano
in A,
nella classe B si rivolgano a nestedclass2"
Ciao
Gaetano
--
#exclude <windows>
printf("\t\t\b\b\b\b\b\b");.
printf("\t\t\b\b\b\b\b\b");
-- 
Posted from 
nts-03.mm.eutelsat.org
 [194.214.173.15] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 
Mi spiego meglio:
class A {
        class nestedclass {...]
        nestedclass var;
}
class B : public A {
        class nestedclass2 {...}
}
Non mi sta bene che la variabile ereditata var si riferisca ancora a 
nestedclass, mentre io vorrei che si riferisse a nestedclass2.
Come posso cambiare l'implementazione delle classi per ovviare a questo???
ps: non ti sei piů fatto sentire per CMatriX???

 ps: non ti sei più fatto sentire per CMatriX???
Sto facendo altro, ma non appena posso mi ci rimetto, a proposito
per la storia delle citta in rete ?
Ciao
Gaetano
--
#exclude <windows>
printf("\t\t\b\b\b\b\b\b");.
printf("\t\t\b\b\b\b\b\b");
-- 


 rivolgano a nestedclass2.
non ho capito bene. Puoi fare un esempio chiarificatore? Probabilmente 
ci sono dei modi piu' puliti di fare quello che vuoi.
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 Come posso cambiare l'implementazione delle classi per ovviare a questo???
Ma allora (ri)definiscila in B::nestedclass2 no?
Se la definisci solo in A::nestedclass, a cosa si dovrebbe riferire se non a
A::nestedclass? Va be che derivi, ma non ridefinisci.
Ciao
--
Luigi
http://web.tiscali.it/luigi_web
byte...@hotmail.com
ICQ 46240443

 
non credo che questo codice compili, in quanto nel punto delle 
dichiarazioni del template A::nestedclass e B::nestedclass2 non sono 
ancora ne' dichiarate ne' definite. Inoltre questo non produce 
l'effetto voluto, dato che cosi' facendo questo codice sarebbe illegale:
        A* p = new B;
dato che B *non* deriva da A (ovvero A<A::nestedclass>) ma da 
A<B::nestedclass2>.


 nestedclass, mentre io vorrei che si riferisse a nestedclass2.
Non ha molto senso, dato che A::nestedclass e B::nestedclass2 sono 
completamente slegate l'una dall'altra. Immagina questo:
class A {
        class nested1 {
        public:
                void foo();
        };
        nested1 var;
public:
        void bar() {
                var.foo();
        }
};
Sin qua va tutto bene e non c'e' nulla di strano. Ma se noi facciamo:
class B: public A {
        class nested2 {
        public:
                void foo2();
        };
        // istruzione che magicamente cambia il tipo di var 
        //da "nested1" a "nested2"
};
Cosa dovrebbe succedere quando richiami la funzione B::bar()? Essa 
cerca di richiamare il metodo foo() sulla variabile var, ma come 
potrebbe fare, dato che var e' "magicamente" diventata di tipo nested2 
e che nested2 non ha alcun metodo foo()?


 ciao Anto
Credo che l'OP si intendesse derivare la seconda classe nidificata dalla 
prima. Se la mia interpretazione e' corretta, una cosa del genere dovrebbe 
andar bene:
class A {
        class Nested {
                // ...
        public:
                virtual void foo();
                virtual ~Nested();
 
        };
        Nested * nested;
        virtual Nested * createNested() { return new Nested; }
 
protected:
        void init() { if (!nested) nested = createNested(); }
public :
        A() { nested = 0; }
        virtual ~A() { delete nested; }
        void bar() { init(); nested->foo(); }
 
        // ...
};
class B : public A {
        class Nested2 : public A:Nested {
                // ...
        public:
                virtual void foo();             
        };
 
        virtual Nested * createNested() { return new Nested2; }
 
        // ...
};
Codice non compilato, ma dovrebbe rendere l'idea.
Auguri,
Fabio
-- 
Posted from 
flopiano.mm.eutelsat.org
 [194.214.173.28] 


Fabio Lopiano wrote:

non so se funziona. La chiamata a createNested avviaente all'interno 
del costruttore di A, quando la parte "B" dell'istanza non e` ancora 
stata costruita: quindi la funzione chiamata sara' sempre 
A::createNested.
Avevo pensato anche io ad una cosa del genere, ma non l'avevo postata 
proprio per questo problema; pero` adesso mi e` venuta in mente una 
possibile soluzione:
class A::Nested1; // e` corretta questa dichiarazione, vero?
class NestedContainer {
protected:
        A::Nested1 * nested;
        NestedContainer(A::Nested1* n): nested(n) { }
};
class A: virtual protected NestedContainer {
protected:
        class Nested1 {
                ...
                virtual ~Nested1();
        };
public:
        A(): NestedContainer( new Nested1 ) { ... }
        ...
};
class B: public A {
        class Nested2: public A::Nested1 { ...}
public:
        B(): NestedContainer( new Nested2 ) { ... }
        ...
};
Non ho compilato, ma dovrebbe funzionare. La cosa funziona perche una 
classe base virtuale deve essere sempre inizializzata esplicitamente da 
qualsiasi derivata, diretta o indiretta, quindi ogni classe puo` 
inizializzarla come meglio crede.
E, tra l'altro, abbiamo anche trovato una qualche utilita` per 
l'ereditarieta` protetta! ;-)


 l'ereditarieta` protetta! ;-)
In effetti e' un'idea interessante.
La classe Nested (definita come interfaccia pura nella classe da cui si
deriva in maniera virtuale protetta)  puo essere vista come una policy,
e le varie classi della gerarchia possono cambiare la policy quando 
vogliono, pur ereditando dalle classi base i metodi concreti che la usano.
Saluti,
Fabio 
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 ancora ne' dichiarate ne' definite.
Non solo, ma le classi annidate non sono utilizzabili come argomenti di
template, perche' non hanno linkage esterno.
Ciao,
Nicola

 class A::Nested1; // e` corretta questa dichiarazione, vero?
Comeau C/C++ 4.2.45.2 (Apr 12 2001 10:06:52) for ONLINE_EVALUATION
Copyright 1988-2001 Comeau Computing.  All rights reserved.
MODE:strict errors C++
"24335.c", line 1: error: name followed by "::" must be a class or
namespace
          name... Wild guess: Did you #include the right header?
  class A::Nested1;
        ^
1 error detected in the compilation of "24335.c".
E se lo dice lui...
Ciao,
Nicola

 template, perche' non hanno linkage esterno.
E' qualche giorno che ci penso ma non ci arrivo proprio.
Spiegamela. O semplicemente dammi un riferimento allo standard.
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

 Spiegamela. O semplicemente dammi un riferimento allo standard.
3.5 in generale e 3.5-8 in particolare, dove dice:
"Names not covered by these rules have no linkage. Moreover, except as
noted, a name declared in a local scope (3.3.2) has no linkage. A name
with no linkage (notably, the name of a class or enumeration declared in
a local scope (3.3.2)) shall not be used to declare an entity with
linkage.
[...] 
This implies that names with no linkage cannot be used as template
arguments (14.3)."
Ciao,
Nicola

 wrote in message
news:3C344EC0...@divalsim.it...

Si. Però 3.5 sub 5 a me sembra che dica esplicitamente che una classe
nestata ha external linkage se la classe in cui è nestata ha external
linkage. Tu invece sembri voler dire che tutte le classi annidiate non
hanno external linkage.
Inoltre sembri dire che un argomento di template deve avere external
linkage. Mentre il brano che riporti dice che non puoi usare come
argomenti per template nomi senza linkage. Un eventuale nome con
internal linkage dovrebbe essere usabile come argomento di template.
Solo che su questo secondo punto forse è lo stesso. Di fatto ci sono
solo tre tipi di linkage: nessuno, interno o esterno. Nel caso nessuno
non puoi usare il nome come argomento del template. Il caso interno, in
realtà, dovrebbe riguardare solo dati e funzioni. In altre parole non
credo sia possibile che il nome di un tipo possa avere internal linkage.
Pertanto, di fatto, resta solo l'esternal linkage come dicevi tu.


 hanno external linkage.
Hai ragione. Mi sembrava di aver letto da qualche parte che le classi
nidificate non potessero essere usate come argomenti di template ed ho
frainteso il paragrafo dello standard.
In realta' sono solo le classi locali che non possono essere usate come
argomento di template.
Ciao,
Nicola

   class A::Nested1;
bene... e allora come si fa un forward declaration di una classe nested?


 Hai letto il codice un po' frettolosamente.
hai ragione ;-). Era il nome "init" ad avermi confuso; allora e` 
possibile rendere il codice piu` robusto:
class A {
protected:
        class Nested1 { ... };
private:
        Nested1* a
public:
        virtual Nested1* create_Nested();
        Nested1& get_a() {
                if (!a) a = create_Nested();
                return *a;
        }
        ecc. ecc.
};
In effetti questa soluzione e` forse la piu` pulita: l'unico 
inconveniente e` che tutti i costruttori di A devono inizializzare "a" 
a 0. Per rendere il tutto piu` sicuro lo si puo` incapsulare in una 
classe, magari templated. Rimane pero` l'inconveniente della forward 
declaration della classe nested.
template< class T >
class Nested_container {
        T* data;
        virtual T* create_nested() = 0;
protected:
        T& get_nested()
        {
                if (!data) data = create_nested();
                return *data;
        }
        Nested_container(): data(0) { }
};
class A_nested1;
class A: protected Nested_container<A_nested1> {
        A_nested1* create_nested() { return new A_nested1; }
        ...
};
Inoltre ci sarebbero dei grossi inconvenienti in caso di ereditarieta` 
multipla da parte di piu` Nested_container.


 bene... e allora come si fa un forward declaration di una classe nested?
Fuori dalla classe contenente non e' possibile.
Ciao,
Nicola

 solo tre tipi di linkage: nessuno, interno o esterno. 
quando e` che non abbiamo alcun tipo di linkage?


 quando e` che non abbiamo alcun tipo di linkage?
Negli unnamed namespace.
--


Negli unnamed namespace.
Non mi sembra esatto... dai miei documenti le definizioni sono:
 --When  a  name  has  external  linkage,  the entity it
   denotes can be referred to by names from scopes of
   other translation units or  from other scopes of
   the same translation unit.
 --When  a  name  has  internal  linkage,  the entity it
   denotes can be referred to by names from other scopes
   in the same translation unit.
 --When a name has no linkage, the entity it denotes
   cannot be referred to by names from other scopes.
I nomi definiti in un unnamed namespace possono avere
formalmente external linkage anche se non risulta possibile
accedervi da altre compilation unit (7.3.1.1. sul draft
in mio possesso). Praticamente il linkage somiglia molto
a quello "internal" (in fondo l'unnamed namespace non nasce
per sopperire ai limiti delle dichiarazioni static ?).
Una variabile locale, invece, non ha nessun linkage in
quanto non puo' essere riferita in alcun ambito al di
fuori del suo scope.
Andrea

 fuori del suo scope.
Gia. Ogni volta mi scordo che fare
namespace {
}
equivale a scrivere
namespace XSAFSDFA {
}
using XSAFSDFA
con il "nome" XSAFSDFA diverso per ogni TU.


 Fuori dalla classe contenente non e' possibile.
ne prendo atto... ma perche`?
Non ci vedrei nulla di male; come mai non hanno previsto questa 
possibilita`?


 possibilita`?
Penso per non complicare le cose. A naso mi pare che l'operatore ::
possa avere alla sua sinistra solo entita' definite ( classi, namespace
), tant'e' che per poter scrivere:
using A::B;
devo almeno avere una dichiarazione forward:
namespace A { class B; }
Questo non si puo' fare con una classe, perche' non e' possibile
riaprirne la definizione. D'altronde mi pare ragionevole che una classe
innestata possa esser definita solo se la classe contenente e' definita,
altrimenti che senso avrebbe l'innestamento?
Ciao,
Nicola

con il "nome" XSAFSDFA diverso per ogni TU.
Lo standard dice una cosa diversa... ovvero che e' equivalente
a fare:
   namespace XSAFSDFA { /* Vuoto! */ }
   using namespace XSAFSDFA;
   namespace XSAFSDFA
   {
     ...
   }
Non mi sono pero' fermato a pensare sul perche' di questa
specie di "forward declaration" del namespace...
Andrea

    }
Il motivo di quel namespace vuoto non mi e' chiaro nemmeno
a me ecco perche' ricordavo la versione da me postata.
