前方声明不会做

The*_* do 6 c++ forward-declaration

下面是代码的两个片段(准备编译).在第一个片段中,我只使用结构的前向声明,同时从Guest类删除指向此结构的指针,不调用Guest类.
在第二个片段中,而不是前向声明我使用基本工作中的删除使用此Guest类的完整定义.
为什么?为什么会有所作为?是不是前向声明假设只是编译器的一个注释,说这个类/结构的定义在其他地方?
我很惊讶它只是不直观地工作.

//First just forward dclr  
#include "stdafx.h"
#include <iostream>
using std::cout;

struct Guest;

struct Base
{
    Guest* ptr_;
    Base(Guest* ptr):ptr_(ptr)
    {
        cout << "Base\n";
    }
    ~Base()
    {
        cout << "~Base\n";
        delete ptr_;
    }
};

struct Guest
{
    Guest()
    {
        cout << "Guest\n";
        throw std::exception();
    }
    Guest(int)
    {
        cout << "Guest(int)\n";
    }
    ~Guest()
    {
        cout << "~Guest\n";
    }
};

struct MyClass : Base
{
    Guest g;
    MyClass(Guest* g):Base(g)
    {
        cout << "MyClass\n";

    }
    ~MyClass()
    {
        cout << "~MyClass\n";
    }
};
int _tmain(int argc, _TCHAR* argv[])
{
    try
    {
        Guest* g = new Guest(1);
    MyClass mc(g);
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what();
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

//第二 - 完全def

#include "stdafx.h"
#include <iostream>
using std::cout;

struct Guest
{
    Guest()
    {
        cout << "Guest\n";
        throw std::exception();
    }
    Guest(int)
    {
        cout << "Guest(int)\n";
    }
    ~Guest()
    {
        cout << "~Guest\n";
    }
};

struct Base
{
    Guest* ptr_;
    Base(Guest* ptr):ptr_(ptr)
    {
        cout << "Base\n";
    }
    ~Base()
    {
        cout << "~Base\n";
        delete ptr_;
    }
};



struct MyClass : Base
{
    Guest g;
    MyClass(Guest* g):Base(g)
    {
        cout << "MyClass\n";

    }
    ~MyClass()
    {
        cout << "~MyClass\n";
    }
};
int _tmain(int argc, _TCHAR* argv[])
{
    try
    {
        Guest* g = new Guest(1);
    MyClass mc(g);
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what();
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

mka*_*aes 16

从C++标准(5.3.5/5):

如果被删除的对象在删除时具有不完整的类类型,并且完整的类具有非平凡的析构函数或释放函数,则行为是未定义的.

因此,您不能在不完整类型上使用删除.它会调用析构函数,编译器还没有意识到它.


Ste*_*sop 3

非正式地:编译器需要类定义才能正确删除对象,因为它需要知道如何调用operator delete该类的析构函数。

正式来说,5.3.5/5:

如果要删除的对象在删除时具有不完整的类类型,并且完整的类具有非平凡的析构函数或释放函数,则行为未定义。

如果(例如)Guest是 POD,那么你就可以了,但是你给了它一个析构函数,所以你就不行了。