开发者

Pointer Reference Pattern - Common use?

开发者 https://www.devze.com 2023-03-18 04:25 出处:网络
In a system where current object is operated by other contained objects, when reference to current object is passed, it appears that the link goes on and on....without any end ( For the code below, Ca

In a system where current object is operated by other contained objects, when reference to current object is passed, it appears that the link goes on and on....without any end ( For the code below, Car->myCurrentComponent->myCar_Brake->myCurrentComponent->myCar_Brake->myCurrentComponent ....).

ICar and Car->myCurrentComponent->myCar_Brake refer to same address, point to same objects. It's like Car contains Brake which refers to Car.

In fact, Car is the only object, myCar_Brake and myCar_Speed just refer(point) to it.Is this kind of use of reference and pointer normal? Are there any potential problem with this approach?

Sample Code

class Brake
class C

class   Car
{

public:

Car();
// Objects of type B and C.
Brake*  myBrake;
Speed*  mySpeed;

// Current component under action.

Component*  myCurrentComponent;

}
/******************************/
// Constructor

Car::Car()
{
myBrake = new Brake(*this);
mySpeed = new Speed(*this);

myCurrentComponent = myBrake;
}

/******************************/
class   Brake: public   Component
{

public:

Brake(Car&);
// Needs to operate on A.
Car*    myCar_Brake;

}

// Constructor
Brake::Brake(Car&)
{
myCar_Brake = Car;
}

/***************开发者_开发知识库***************/
class Speed
{

public:

Speed(Car&);

// Needs to operate on A.
Car*    myCar_Speed;

}

// Constructor
Speed::Speed(Car&)
{
myCar_Speed = Car;
}

/****************************/


There's no fundamental problem with having circular references in your object graph, so long as you understand that and don't try to traverse your object graph without keeping track of which objects you've encountered. To specifically answer your question, having circular references between objects is relatively common; it's the way a doubly-linked list works, for example.


Although, as Paul mentions, there is no problem with having circular references, the above code example is totally missing encapsulation and is not memory leak safe.

Does it make sense to allow something like this?

Speed::Speed(Car& value)
{
  myCar_Speed = value;
  // WTF code below
  value->myCurrentComponent->myCar_Brake = NULL;
}

Also,

Car::Car()
{
  myBrake = new Brake(*this);
  mySpeed = new Speed(*this);
  //if Speed::Speed(Car&) throws an exception, memory allocated for myBrake will leak
  myCurrentComponent = myBrake;
}

Never use raw pointers without some kind of a resource manager.


Without debating the validity of the actual object structure of the relation of Car, Break and Speed, this approach has one minor problem: it can be in invalid states.

If - something - goes wrong, it is possible in this setup, that a Car instance#1 has a Break instance#2 that belongs to a Car instance#3. A general problem with doubly-linked lists too - the architecture itself enables invalid states. Of course careful visibility modifier choosing and good implementation of functions can guarantee it will not happen. And when its done and safe, you stop modifying it, take it as a 'black box', and just use it, thus eliminating the probability of screwing it up.

But, I'd personally recommend to avoid architectures that allow invalid states for high level, constantly maintained code. A doubly-linked list is a low level balck box code that will most likely not need any code changes, like ever. Can you say that about your Car, Break and Speed?

If a Car had a Break and Speed, and Break and Speed would not know of their "owning Car", it would be impossible to make and invalid state. Of course, it might not suit the concrete situation.

0

精彩评论

暂无评论...
验证码 换一张
取 消