Domanda

[Tutti i seguenti è stata testata utilizzando Visual Studio 2008 SP1]

In C++, const qualifica di tipi di parametro non influenza il tipo di funzione (8.3.5/3:"Qualsiasi cv-qualificatore di modifica di un tipo di parametro viene eliminato")

Così, per esempio, nel seguente gerarchia di classe, Derived::Foo sostituzioni Base::Foo:

struct Base
{
    virtual void Foo(const int i) { }
};

struct Derived : Base
{
    virtual void Foo(int i) { }
};

Prendere in considerazione una simile gerarchia in C++/CLI:

ref class Base abstract
{
public:
    virtual void Foo(const int) = 0;
};

ref class Derived : public Base
{
public:
    virtual void Foo(int i) override { }
};

Se poi creare un'istanza di Derived:

int main(array<System::String ^> ^args)
{
    Derived^ d = gcnew Derived;
}

compila senza errori o avvisi.Quando ho eseguito, viene generata l'eccezione seguente e quindi termina:

Un'eccezione non gestita di tipo 'System.TypeLoadException' si è verificato in ClrVirtualTest.exe

Informazioni aggiuntive:Metodo di 'Pippo' nel tipo 'Derivato'...non ha un'implementazione.

L'eccezione sembra indicare che la const qualificazione del parametro non influenzare il tipo di funzione in C++/CLI (o, almeno, colpisce l'override in qualche modo).Tuttavia, se commento la riga contenente la definizione di Derived::Foo, il compilatore segnala il seguente errore (sulla linea di main in cui l'istanza di Derived viene creata un'istanza):

errore C2259:'Derivato':impossibile creare un'istanza della classe astratta

Se posso aggiungere il qualificatore const al parametro di Derived::Foo o rimuovere il qualificatore const dal parametro di Base::Foo, si compila e si esegue senza errori.

Penso che se const di qualificazione del parametro influenza il tipo di funzione, mi dovrebbe arrivare questo messaggio di errore se il const qualificazione del parametro nella classe derivata di funzione virtuale non corrisponde const di qualificazione del parametro nella classe base virtuale funzione.

Se cambio il tipo di Derived::Foo's parametro da un int per un double, Ottengo il seguente messaggio di avviso (oltre al già citato errore, C2259):

avviso C4490:"override":utilizzo non corretto di ignorare identificatore;'Derivata::Foo' non corrisponde una base ref metodo di classe

Così, la mia domanda è, effettivamente, non const di qualificazione della funzione di parametri influenzano il tipo di funzione in C++/CLI?Se è così, perché questa compilare e perché non ci sono errori o avvisi?Se non è così, perché è un'eccezione?

È stato utile?

Soluzione

Beh, è un bug.Const modificatori emesso nei metadati con il modopt modificatore personalizzato.Purtroppo, il C++/CLI regole della lingua non corrispondono CLI regole.Capitolo 7.1.1 del CLI spec dice:

Personalizzato modificatori, definita con modreq (“richiesta modificatore”) e modopt (facoltativo“modificatore”), sono simili a attributi personalizzati (§21), salvo che i modificatori sono parte di una firma invece di essere collegato a adeclaration.Ogni modificatore associates un tipo di riferimento, con un elemento in firma.

Il CLI è il trattamento richiesto e modificatori facoltativi nella stessa modo.Due firme che differiscono solo con l'aggiunta di una custom modificatore (obbligatorio o facoltativo), dovrà non saranno considerati match.Personalizzato i modificatori non hanno altro effetto operazione della VES.

Così, il CLR dice che la Derivata::Foo() non è una sostituzione, C++/CLI, dice.Il CLR vince.

Si potrebbe segnalare il bug connect.microsoft.com ma è probabilmente uno spreco di tempo.Penso che questa incompatibilità è stato intenzionale.Essi dovrebbero hanno cambiato le regole del linguaggio C++/CLI, ma sicuramente il pensiero C++ compatibilità di essere più importante.CV modificatori sono un dolore comunque, ci sono altri scenari che non sono ben supportati, puntatori const const per uno.Questo non può essere applicata in fase di runtime, comunque, il CLR non ha il supporto per esso.

Altri suggerimenti

Si tratta di un bug, e non è specifico per C++/CLI.

https://connect.microsoft.com/VisualStudio/feedback/details/100917/argument-const-ness-is-part-of-member-function-type-signature

Fatto è che il compilatore C++ dovrebbe spogliarsi di livello superiore const/volatile.Solo const/volatile su la punta-tipo di un puntatore o un riferimento importante.Se il compilatore fatto correttamente, il CLR non dire cosa sta succedendo.

BTW questo è il generati dal compilatore /clr:puro

.class private abstract auto ansi beforefieldinit Base
    extends [mscorlib]System.Object
{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 1
        L_0000: ldarg.0 
        L_0001: call instance void [mscorlib]System.Object::.ctor()
        L_0006: ret 
    }

    .method public hidebysig newslot abstract virtual instance void Foo(int32 modopt([mscorlib]System.Runtime.CompilerServices.IsConst)) cil managed
    {
    }

}

.class private auto ansi beforefieldinit Derived
    extends Base
{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 1
        L_0000: ldarg.0 
        L_0001: call instance void Base::.ctor()
        L_0006: ret 
    }

    .method public hidebysig virtual instance void Foo(int32 i) cil managed
    {
        .maxstack 0
        L_0000: ret 
    }

}

Questo sicuramente viola la regola di James elencati in materia di eliminazione di alto livello di qualifiche.

Ulteriori sezioni pertinenti del C++/CLI spec:

8.8.10.1 Funzione di override

[snip]

  1. Una classe derivata della funzione esplicitamente esegue l'override di una classe base virtuale funzione con lo stesso nome, il parametro di tipo a-elenco e cv-qualifica, utilizzando la funzione di modificatore di override, con il programma in fase di malformati se tale classe base virtuale funzione esiste

12.3 Dichiaratore tipi

Il C++ Standard (§8.3.5/3) è aumentata, come segue:
La lista di trasformato i tipi di parametro e la presenza o l'assenza dei puntini di sospensione è la funzione del parametro di tipo lista.

Così mi sono portato a credere che la regola di eliminazione di cv-qualificazione si applica a C++/CLI, perché la spec chiama specificamente sezione 8.3.5/3 Standard ISO C++.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top