2013-05-21 10 views
7

Mi sono imbattuto in una domanda durante l'esecuzione del test iKM. C'era una classe base con due metodi astratti con specificatore di accesso privato. C'era una classe derivata che sovrascriveva questi metodi astratti ma con un identificatore di accesso protetto/pubblico.override con le specifiche di accesso alle differenze C++

Non mi sono mai imbattuto in una cosa del genere in cui i metodi sovrascritti nella classe derivata avevano specifiche di accesso diverse. È permesso? Se sì, è conforme alla relazione "IS A" tra base e derivata (cioè sostituibile in modo sicuro).

Potrebbe indicarmi alcuni riferimenti che possono fornire maggiori dettagli su tali usi delle classi?

Grazie.

risposta

1

Come molti hanno sottolineato, è legale.

Tuttavia, la parte "IS-A" non è così semplice. Quando si parla di "polimorfismo dinamico", la relazione "IS-A" vale, io. tutto ciò che puoi fare con Super puoi farlo anche con l'istanza derivata.

Tuttavia, in C++ abbiamo anche qualcosa che viene spesso definito come polimorfismo statico (modelli, il più delle volte). Si consideri il seguente esempio:

class A { 
public: 
    virtual int m() { 
     return 1; 
    } 
}; 

class B : public A { 
private: 
    virtual int m() { 
     return 2; 
    } 
}; 

template<typename T> 
int fun(T* obj) { 
    return obj->m(); 
} 

Ora, quando si tenta di utilizzare "il polimorfismo dinamico" tutto sembra essere ok:

A* a = new A(); 
B* b = new B(); 

// dynamic polymorphism 
std::cout << a->m(); // ok 
std::cout << dynamic_cast<A*>(b)->m(); // ok - B instance conforms A interface 
// std::cout << b->m(); fails to compile due to overriden visibility - expected since technically does not violate IS-A relationship 

...ma quando si utilizza "il polimorfismo statico" si può dire che "is-a" relazione non regge più:

A* a = new A(); 
B* b = new B(); 

// static polymorphism 
std::cout << fun(a); // ok 
//std::cout << fun(b); // fails to compile - B instance does not conform A interface at compile time 

Così, alla fine, cambiando la visibilità per il metodo è "piuttosto legale", ma questo è uno dei più brutti cose in C++ che possono portare a trabocchetti.

1

Sì, questo è consentito a condizione che la firma sia la stessa. E a mio parere, sì, hai ragione, la visibilità prevalente (ad esempio, pubblica -> privata) interrompe IS-A. Credo che la serie Scott Myers Effective C++ abbia una discussione su questo.

+0

grazie controllare il riferimento che hai indicato. Grazie. – irappa

+0

Non credo che si rompa * è-a * ma senza comprare il libro non saprei. Scott Meyers potrebbe essere [uno dei 5 più importanti C++, secondo alcuni] (http://www.artima.com/cppsource/top_cpp_people.html), ma ha una scarsa presenza on-line. –

2

È consentito, in entrambe le direzioni (ovvero, da private a public E da public a private).

D'altro canto, direi che non infrange la relazione IS-A. Baso la mia tesi su 2 fatti:

  • usando un Base& (o Base*) gestire, si ha esattamente la stessa interfaccia di prima
  • si potrebbe perfettamente (se lo si desidera) introdurre un metodo in avanti che è public e chiamando il metodo private direttamente in ogni caso: stesso effetto con più digitando
2

Sì, questo è legale, l'accessibilità viene controllato in modo statico (non dinamico):

class A { 
public: 
    virtual void foo() = 0; 
private: 
    virtual void bar() = 0; 
}; 

class B : public A { 
private: 
    virtual void foo() {} // public in base, private in derived 
public: 
    virtual void bar() {} // private in base, public in derived 
}; 

void f(A& a, B& b) 
{ 
    a.foo(); // ok 
    b.foo(); // error: B::foo is private 
    a.bar(); // error: A::bar is private 
    b.bar(); // ok (B::bar is public, even though A::bar is private) 
} 

int main() 
{ 
    B b; 
    f(b, b); 
} 

Ora, perché vorresti farlo? Importa solo se si utilizza direttamente la classe derivata B (2 ° parametro di f()) anziché tramite l'interfaccia di base A (1 ° parametro di f()). Se si utilizza sempre l'interfaccia astratta A (come suggerirei in generale), è comunque conforme alla relazione "IS-A".

Problemi correlati