【问题标题】:Getting System.AccessViolationException while calling a memberfunction using pointer to a class使用指向类的指针调用成员函数时获取 System.AccessViolationException
【发布时间】:2013-01-09 04:28:12
【问题描述】:
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 接收中的上层->接收时,我得到了一个运行时异常:System.AccessViolationException。为什么我会得到它?

【问题讨论】:

    标签: c++ design-patterns inheritance protocols dereference


    【解决方案1】:

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

    只需在DataLink_Layer 构造函数中调用upper-&gt;receive() 即可更清楚地看到这一点。

    这个FAQ 解释了更多关于在构造函数中使用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() 函数即可。

    【讨论】:

    • 但是.. 当我从 Physical_layer 的接收函数中调用 DataLink_Layer 的接收函数时,它工作正常。
    • 直到lower-&gt;send() 在DataLink_Layer 构造函数中被调用,此时DataLink_LayerLayer 基类已经被构造,你才能调用它。
    • 除了显式调用发送和接收之外,还有其他方法吗?场景就像我应该在连接建立期间发送一个特定的数据帧。所以我正在考虑使用构造函数来完成这项工作。
    • @sajas 构造不应该真正用于像发送数据帧这样的繁重工作,尤其是不能像这样复杂的继承。我没有看到其他方式。
    • 感谢您的回答。我还有 1 个问题。当我将 Layer 类(下层和上层)中的属性作为每个派生层的私有变量并尝试使用这些属性调用虚拟函数时,我能够做到这一点。然后调用正确的虚函数。根据您提供的常见问题解答链接,这应该发生吗?
    猜你喜欢
    • 1970-01-01
    • 2015-05-06
    • 2013-01-26
    • 1970-01-01
    • 2021-06-06
    • 2017-07-27
    • 2013-06-06
    • 2011-07-10
    相关资源
    最近更新 更多