For Programmers: Free Programming Magazines  


Home > Archive > VC STL > August 2005 > How to access the source of a copied object









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author How to access the source of a copied object
mats.g.friberg@datarutin.se

2005-08-22, 3:59 am

I want to have a reference to the source object in the receiving object
after a copy (Copy ctr or assignment). I dont want the receiving object
to be able to modify contents in the copied object.

How should i do this?

Here is my first stab at a solution, but its not working.
Its the dynamic downcast from Base* to SubA* that fails when i run. I
want to use a dynamic cast since i sometimes need to do a runtime check
to see if an object is if a certain type. I need to do a downcast to be
able to check the values of the original (source) object.

So how can i have access to the source object, use it as the downcasted
subtype ,and restrict that access to be read-only.


class Base
{
public:
Base() : sourceObj(NULL) {}
virtual ~Base() {}

Base(const Base& other)
{
*this = other
}
Base& operator=(const Base& other)
{
sourceObj = &other;
return *this;
}

protected:
const Base* sourceObj;

}

class SubA : Base
{
public:
SubA() : Base() {}
~SubA() {}
SubA(const SubA& other) : Base(other) {}

int anAttribute;

void checkAttributeOfSource()
{
// Line below casts an error when run in MS VC++ .NET
SubA* a = dynamic_cast<SubA*>(sourceObj);
if (a->anAttribute = 1)
{
// do something
}
}
}

// ---- Main snippet --------
Base* aBase = new SubA();
// Line below casts an error when run in MS VC++ .NET
SubA* aSub = dynamic_cast<SubA*>(aBase);


// --- Scenario B
SubA a1.readFromdatabase();
SubA a2(a1);
a2.ReadFromClient();

// Here i want to be able to query values in a1 without modifying
a1
a2.CompareMeTosourceObject();

Ulrich Eckhardt

2005-08-22, 7:58 am

(F'up to microsoft.public.vc.language, OT in mpvs anyway.)

mats.g.friberg@datarutin.se wrote:
> I want to have a reference to the source object in the receiving object
> after a copy (Copy ctr or assignment). I dont want the receiving object
> to be able to modify contents in the copied object.
>
> How should i do this?
>
> Here is my first stab at a solution, but its not working.
> Its the dynamic downcast from Base* to SubA* that fails when i run. I
> want to use a dynamic cast since i sometimes need to do a runtime check
> to see if an object is if a certain type. I need to do a downcast to be
> able to check the values of the original (source) object.
>
> So how can i have access to the source object, use it as the downcasted
> subtype ,and restrict that access to be read-only.
>
>
> class Base
> {
> public:
> Base() : sourceObj(NULL) {}
> virtual ~Base() {}
>
> Base(const Base& other)
> {
> *this = other
> }
> Base& operator=(const Base& other)
> {
> sourceObj = &other;
> return *this;
> }
>
> protected:
> const Base* sourceObj;
>
> }


This doesn't work. The problem is called 'slicing' or 'truncation' (see FAQ
at parashift.com) and typically arises when you are trying to mix entity
behaviour (i.e. virtual interface with different implementations in derived
classes) and value semantics (objects are freely assignable and copyable).
The main problem is that you can assign 'aBase = aDerived' but this will
only copy some data and none of the behaviour.

If you want to mix these two, you need a kind of handle that knows how to
copy objects, best implemented when all objects know how to make a copy of
themselves (name copy-constructor idiom, clone-method). This handle will
replace the base how you currently use it. Still, you don't get real
assignability except by using destroy and copy in the back. Using smart
pointers helps implementing that, too, btw.

> // Line below casts an error when run in MS VC++ .NET
> SubA* a = dynamic_cast<SubA*>(sourceObj);
> if (a->anAttribute = 1)
> {
> // do something
> }


Your code is wrong/bad here. In general, when using dynamic_cast on
pointers, you should write it like this:
if( Derived* pd = dynamic_cast<Derived*>(pb))
... // derived
else
... // not derived
i.e. check the returnvalue. When using references you can omit that since
then it throws a bad_cast in case of failure.


> class SubA : Base
> {...};
> Base* aBase = new SubA();


This line can't compile because Base is not a public baseclass of SubA. I
just stumbled across this after writing most of this posting, but it is a
definite showstopper.

> // Line below casts an error when run in MS VC++ .NET
> SubA* aSub = dynamic_cast<SubA*>(aBase);


IFF this really generates any kind of errror (which you neglected to quote
or describe here), it is due to your setup or above mistake. Otherwise, in
that snippet, aSub will never be null.

Uli



Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com