2015-07-22 17 views
5

Der Artikel MSDN C4673 auf Warnung Dieses Beispiel enthält, die die Warnung mit spezifischer Meldung ausgibt:Verständnis C4673 Compiler-Warnung

Base: this base class is inaccessible 
// C4673.cpp 
// compile with: /EHsc /W4 
class Base { 
private: 
    char * m_chr; 
public: 
    Base() { 
     m_chr = 0; 
    } 

    ~Base() { 
     if(m_chr) 
     delete m_chr; 
    } 
}; 

class Derv : private Base { 
public: 
    Derv() {} 
    ~Derv() {} 
}; 

int main() { 
    try { 
     Derv D1; 
     // delete previous line, uncomment the next line to resolve 
     // Base D1; 
     throw D1; // C4673 
    } 

    catch(...) {} 
} 

Leider versagt der MSDN-Artikel, eine Erklärung zu geben, Das Thema. Ich verstehe nicht, was mit dem obigen Code falsch ist. Warum gibt es eine Warnung?

Dies ist MSVC 2013 - v120 Toolset.

+2

Es ist schwierig, Vorschläge anzubieten, den Code nicht zu sehen – Petr

+0

@Petr: wie gesagt, der Code ist im MSDN-Artikel. Ich werde es hier einfügen. –

+1

Dann schlage ich vor, Ihre Frage zu etwas wie "Ich verstehe das Beispiel nicht ..." umzuformulieren und Ihren Code überhaupt nicht zu erwähnen. – Petr

Antwort

5

Ich kann dies auf webcompiler reproduzieren und den vollständigen Text der Warnung ist:

main.cpp (28): C4673 Warnung: Werfen ‚Derv‘ die folgenden Typen werden nicht an der Fang-Website angesehen werden
main.cpp (28): C4670 Warnung: 'Base': diese Basisklasse ist unzugänglich

das ist wahr. Hätten wir:

try { 
    throw Derv(); 
} 
catch (Base&) { 
    std::cout << "I caught it!"; 
} 

Das Handler würde nicht passen die Derv Ausnahme, da Derv privat erbt von Base und damit Basisklasse ist nicht zugänglich. In diesem Beispiel würde die Ausnahme nicht abgefangen.

Es ist jedoch eine seltsame Warnung ist, als in dem MSDN-Beispiel zu emittieren, wird die Ausnahme mit gefangen werden:

catch(...) {} 

So scheint es, dass die Warnung tatsächlich nicht alles überprüfen - es ist nur ein allgemeines - Warnung, dass Sie etwas Schädliches tun können, ohne tatsächlich zu überprüfen, ob Sie es sind oder nicht. Das scheint mir keine besonders nützliche Warnung zu sein. Wenn wir von Base& fangen, ja - sagen Sie mir, dass das nicht passieren wird - aber wir fangen durch .... Hier

+0

Also das ist es! Private Erbschaft! Ich habe es nicht bemerkt. Durch die Änderung in "public" wird das Problem gelöst. –

+1

... und das Hinzufügen von 'catch (Base &)' im Beispiel oder sogar * das * catch (...) 'wegzulassen, hätte kristallklar gemacht, worum es in der Warnung geht. Ein weiterer dieser MS Edelsteine ​​... – DevSolar

+0

Warnung über 'catch (Base &)' wäre nicht korrekt. Angenommen, es gibt eine Übersetzungseinheit, die die Definition von Base, aber nicht von Derv enthält. Der Compiler würde nicht wissen, dass Derv privat von Base erbt, so dass es keine Möglichkeit gibt, die Warnung auszugeben. – user1610015

3

ist ein reduziertes Beispiel:

class Base { public: virtual ~Base() {} }; 

class Derived : private Base {}; 

int main() 
{ 
    Derived d; 
    throw d; // C4673 
} 

Das Problem hierbei ist, dass ein Entwickler könnte eine throw Aussage wie, dass als Teil einer Funktion schreiben, und dann erwarten, dass die resultierende Ausnahme gefangen wird polymorph als Base . Dies wird nicht funktionieren, da die Vererbung private ist. Sie müssen entweder Derived oder ... fangen.

Der Grund, warum eine Warnung hier angebracht ist, ist, dass Sie nicht irgendein Objekt nur throw. Normalerweise haben Sie bestimmte Ausnahmetypen, die nur dafür verwendet werden. Es macht keinen Sinn, die private Vererbung für solche Ausnahmearten zu verwenden. Es wird nur verwirrendes Verhalten wie dieses einführen, aber es gibt keine echten Anwendungsfälle.

Leider können wir in der throw nur feststellen, ob eine Klasse ein Ausnahme-Typ ist. Dies ist also der einzige Ort, wo wir diese Warnung generieren können.