Получение System.AccessViolationException при вызове функции-члена с использованием указателя на класс

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. Почему я это получаю?

0

Решение

Конструктор DataLink_Layer пытается перезвонить в Application_Layer через Layer* перед Layer базовый класс Application_Layer даже построен (вы все еще оценивает new DataLink_Layer(this) в это время).

Вы можете увидеть это более четко, просто позвонив upper->receive() в DataLink_Layer конструктор.

это Часто задаваемые вопросы объясняет немного больше об использовании 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() функционирует явно после построения.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]