Newsgroup: it.comp.lang.c++
Titolo: funzioni virtuali private

Qualcuno mi sa dire:
a- se il seguente codice e` conforme allo standard
b- se l'output prodotto e` compliant con cio` che dice lo standard
      (qui c'e` stata una piccola discussione sul fatto che una funzione
        virtuale privata non dovesse poter essere ridefinita ,
         nemmeno se virtuale)
c- se f1 della classe A fosse virtuale pura,  e` giusto ottenere un
errore dal compilatore
      del tipo
g++ a.cc
a.cc: In function `int main()':
a.cc:28: cannot declare variable `a' to be of type `A'
a.cc:28:   since the following virtual functions are abstract:
a.cc:28:        void A::f1()
Grazie,
Marco Guidi.
//file a.cc
#include <iostream>
class A {
    virtual void f1() { cout << "f1 di A" << endl; }
            void f2() { cout << "f2 di A" << endl; }
public:
    void call() {
        f1();
        f2();
    }
    A(){};
    ~A(){};
};
class B : public A {
    virtual void f1() { cout << "f1 di B" << endl; }
            void f2() { cout << "f2 di B" << endl; }
public:
    B(){};
    ~B(){};
};
int main() {
    A a;
    B b;
    a.call();
    b.call();
}
[mg@pegasus prove]$ g++ a.cc
[mg@pegasus prove]$ ./a.out
f1 di A
f2 di A
f1 di B
f2 di A
[mg@pegasus prove]$ g++ --version
egcs-2.91.66
[mg@pegasus prove]$

       del tipo
Chiedo scusa,  chiaramente e` giusto avere quell'errore. La domanda voleva
essere
c- se f1 della classe A fosse virtuale pura, (e se si cancella dal main
tutto cio` che riguarda l'oggetto a),
      e` giusto ottenere:
[mg@pegasus prove]$ !g
g++ a.cc
[mg@pegasus prove]$ ./a.out
f1 di B
f2 di A
[mg@pegasus prove]$
Grazie ancora,
Marco Guidi

 f2 di A
Certo.  Infatti f2 non e` virtuale, e che B la nasconda e`
chiaramente irrilevante poiche` l'accesso e` via un A*.
Alex

Alex Martelli wrote:

Si pero` secondo un mio collega il fatto che f1 sia privata, anche se
virtuale,
avrebbe dovuto  generare un errore in compilazione,
in quanto i membri privati non dovrebbero poter essere ereditati e/o
ridefiniti, nemmeno quando virtuali.
Cioe`, secondo lui il seguente codice non avrebbe dovuto poter essere
compilato
#include <iostream>
class A {
    virtual void f1()=0;
            void f2() { cout << "f2 di A" << endl; }
public:
    void call() {
        f1();
        f2();
    }
    A(){};
    ~A(){};
};
class B : public A {
    virtual void f1() { cout << "f1 di B" << endl; }
            void f2() { cout << "f2 di B" << endl; }
public:
    B(){};
    ~B(){};
};
int main() {
    B b;
    b.call();
}
invece:
[mg@pegasus prove]$ !g
g++ a.cc
[mg@pegasus prove]$ ./a.out
f1 di B
f2 di A
[mg@pegasus prove]$
Marco Guidi

Si a tutte e tre, anzi 4 compresa la tua correzione...
f2 in particolare non e` virtuale.
paolo

 ridefiniti, nemmeno quando virtuali.
Assolutamente no, e non e` mai stato cosi` in nessuna versione del C++.
L'accessibilita` permette o vieta di *CHIAMARE* un metodo; essa
non ha alcun effetto sulla possibilita` di farne *OVERRIDE*.  Il design
pattern cosiddetto "Template" (che non ha nulla a che vedere con i
template del linguaggio C++) viene TIPICAMENTE implementato
sulla base di metodi privati virtuali, magari virtuali-puri (dipende), per
garantire che i metodi stessi (che le classi derivate devono o possono
porre in override) siano chiamati in appropriata sequenza e contesto.
Quindi, l'uso di metodi virtuali privati, e il loro override in classi
derivate, non e` neppure un idioma particolarmente raro; e`, anzi,
molto tipico di uno stile di progettazione basato sulle ottime idee di
"Design Patterns".
Alex

grazie per le risposte,
Marco Guidi

 wrote in message
| Si pero` secondo un mio collega il fatto che f1 sia privata, anche se
| virtuale, avrebbe dovuto  generare un errore in compilazione,
| in quanto i membri privati non dovrebbero poter essere ereditati e/o
| ridefiniti, nemmeno quando virtuali.
Per questo ci vuole l'ereditarieta' privata, cioe' un is-implemented-using.
(se non sbaglio il termine)

ridefiniti, nemmeno quando virtuali.
I campi privati sono ereditati al pari degli altri (e i metodi possono
essere ridefiniti), l'accessibilita` e` del tutto ortogonale
all'ereditarieta`.
Che poi la cosa possa essere un errore del programmatore e`
un altro discorso.
Paolo

 (se non sbaglio il termine)
Non cambia.  Anche con eredita` privata, puoi ridefinire i metodi
virtuali privati della base privata.  Se non fosse per ridefinire qualche
metodo, ereditare sarebbe comunque di solito errato.
Alex