得到系统.使用指向类的指针调用成员函数时的AccessViolationException

Getting System.AccessViolationException while calling a memberfunction using pointer to a class

本文关键字:调用 指针 成员 函数 AccessViolationException 系统      更新时间:2023-10-16
using namespace std;
class Layer
{
protected:
    Layer *lower;
    Layer *upper;
public:
    Layer(Layer *lo,Layer *up):lower(lo),upper(up)
    {}
    virtual void send()=0;
    virtual void receive()=0;
};
class Physical_Layer:public Layer
{
public:
    Physical_Layer(Layer *p):Layer(NULL,p)
    {
        cout<<"Physical_Layer constructed"<<endl;
    }
    virtual void send()
    {
        cout<<"Data send from Physical_Layer"<<endl;
        receive();
    }
    virtual void receive()
    {
        cout<<"Physical_Layer calling receive of DataLink_Layer"<<endl;
        upper->receive();
    }
};
class DataLink_Layer:public Layer
{
public:
    DataLink_Layer(Layer *p):Layer(new Physical_Layer(this),p)
    {
        cout<<"DataLink_Layer Constructed"<<endl;
        lower->send();
    }
    virtual void send()
    {
        cout<<"Data send from DataLink_Layer"<<endl;
        lower->send();
    }
    virtual void receive()
    {
        cout<<"DataLink_Layer calling receive of Application_Layer"<<endl;
        cout<<typeid(upper).name()<<endl;

        upper->receive();

    }
};
class Application_Layer:public Layer
{
public:
    Application_Layer():Layer(new DataLink_Layer(this),NULL)
    {
        cout<<"Application_Layer Constructed"<<endl;
        send();
    }
    virtual void send()
    {
        cout<<"Sending data from Application_Layer"<<endl;
        lower->send();
    }
    virtual void receive()
    {
        cout<<"Receiving data at Application_Layer"<<endl;
    }
};
int main()
{
    Layer *l=new Application_Layer();
}

我试图用协议设计模式模拟一个三层协议栈。但是在DataLink_Layer的接收中解引用upper->receive时,我得到一个运行时异常:System.AccessViolationException。为什么我得到它?

Application_LayerLayer基类被构造之前,DataLink_Layer的构造函数试图通过Layer*回调到Application_Layer(此时您仍在评估new DataLink_Layer(this))。

通过在DataLink_Layer构造函数中调用upper->receive()可以更清楚地看到这一点。

本常见问题解答更多地解释了在构造函数中使用this

这个简单的例子可以更清楚地说明这个问题:

struct C;
struct A
{
    A(C* c) {};
    virtual void Foo() = 0;
};
struct C
{
    C(A* a)
    {
        a->Foo();
    }
};
struct B : public A
{
    B() : A(new C(this)) {}
    void Foo() {}
};
int main()
{
    B b;
}

一般来说,不应该使用构造函数对部分构造的对象执行复杂的调用堆栈。只需在构造后显式调用send()receive()函数即可。