Warum muss std :: shared_ptr den vollständigen Typ nicht kennen, wenn er nicht aus Null besteht?

Ich habe eine Factory-Funktion in factory.h, die ein std :: shared_ptr an eine Basisklasse in foo.h zurückgibt. Die Datei factory.h verwendet die Forward-Deklaration für die Basisklasse, anstatt foo.h einzuschließen. Wie der folgende Code:

factory.h:

#include <memory>

// forward declaration
class foo;

std::shared_ptr<foo> create_foo_A(int A);
std::shared_ptr<foo> create_foo_B(int A, int B);
void work_with_foo(std::shared_ptr<foo> ptr);

Wenn in einem Client-Code ein std :: shared_ptr to foo mit nullptr initialisiert wurde, warnt der Compiler.

main.cpp:

#include "factory.h"
int main()
{
    int type = 1;

    std::shared_ptr<foo> ptr(nullptr);    // <--- compile warning
    if (type == 1)
        ptr = create_foo_A(5566);
    else
        ptr = create_foo_B(5566, 7788);
    work_with_foo(ptr);

    return 0;
}

Die Warnmeldung lautet:

warning C4150 : deletion of pointer to incomplete type 'foo'; no destructor called

Es ist vernünftig, da std :: shared_ptr nicht den vollständigen Typ von foo kennt. Diese Warnung kann entfernt werden, wenn main.cpp foo.h enthält.

Wenn jedoch std :: shared_ptr mit non-nullptr initialisiert würde, würde die Kompilierung keine Warnung auslösen. main.cpp:

#include "factory.h"
int main()
{
    int type = 1;

    if (type == 1)
    {
        std::shared_ptr<foo> ptr = create_foo_A(5566);    // <--- OK
        work_with_foo(ptr);
    }
    else
    {
        std::shared_ptr<foo> ptr = create_foo_B(5566, 7788);    // <--- OK
        work_with_foo(ptr);
    }

    return 0;
}

Warum muss std :: shared_ptr in dieser Szene nicht den vollständigen Typ der Klasse foo kennen? Ist es ganz anders, wenn std :: shared_ptr mit nullptr und nicht null erstellt wird?

Antworten auf die Frage(3)

Ihre Antwort auf die Frage