473,806 Members | 2,443 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Is this the easiest way to backup objects?

Problem:

I have a properties dialog. X objects build the dialog, but a subclass
of X, such as Y, can add more options to the dialog for Y specific
properties. I would like to write code for the dialog that creates a
backup of the current object when the dialog pops up, and sets the
current modified object to the backup when the user clicks cancel (or
discards the backup if the user clicks OK). X already has a Clone
method.

(I realize this way of making backups isn't always practical for large
objects, but the ones I'm dealing with are fairly lightweight)

Solutions:

0. Simply write the code using X pointers. Problem: Then only the X
members get set because the assignment operator can't be virtual.

1. Template the dialog class so you can do Dialog<Xor Dialog<Y>,
causing a backup of the appropriate type to be made. Problem: The
dialog code gets a lot uglier just to make 1 line work.

2. Solution below seemed best, but I'm looking for feedback.

This is a compileable test case.

#include <iostream>

template<class T>
class CanBackup {
public:
CanBackup();
~CanBackup();
void MakeBackup();
void RestoreBackup() ;

virtual CanBackup<T>* Clone() = 0;

private:
T* backup;
};

template<class T>
CanBackup<T>::C anBackup()
: backup(NULL)
{
}

template<class T>
CanBackup<T>::~ CanBackup()
{
if(backup)
delete backup;
}

template<class T>
void CanBackup<T>::M akeBackup()
{
backup = (T*)Clone();
}

template<class T>
void CanBackup<T>::R estoreBackup()
{
*((T*)this) = *backup;
}

class A : public CanBackup<A{
public:
A();
~A();
A* Clone();
int x;
};

A::A() {}
A::~A() {}

A* A::Clone()
{
return new A(*this);
}

// Should print: 3 5 3
// Actually prints: 3 5 5
int main() {
A foo;
foo.x = 3;
std::cout << foo.x << std::endl;
foo.MakeBackup( );
foo.x = 5;
std::cout << foo.x << std::endl;
foo.RestoreBack up();
std::cout << foo.x << std::endl;
}

Aug 12 '06 #1
6 1749
k0*****@gmail.c om wrote:
Problem:

I have a properties dialog. X objects build the dialog, but a subclass
of X, such as Y, can add more options to the dialog for Y specific
properties. I would like to write code for the dialog that creates a
backup of the current object when the dialog pops up, and sets the
current modified object to the backup when the user clicks cancel (or
discards the backup if the user clicks OK). X already has a Clone
method.

(I realize this way of making backups isn't always practical for large
objects, but the ones I'm dealing with are fairly lightweight)

Solutions:

0. Simply write the code using X pointers. Problem: Then only the X
members get set because the assignment operator can't be virtual.
Says who? Have you tried making it virtual? Did it not work?
1. Template the dialog class so you can do Dialog<Xor Dialog<Y>,
causing a backup of the appropriate type to be made. Problem: The
dialog code gets a lot uglier just to make 1 line work.

2. Solution below seemed best, but I'm looking for feedback.

This is a compileable test case.

#include <iostream>

template<class T>
class CanBackup {
public:
CanBackup();
~CanBackup();
void MakeBackup();
void RestoreBackup() ;

virtual CanBackup<T>* Clone() = 0;
Please drop the "<T>" inside the template. It only confuses
the readers of your code and adds nothing to it.
>
private:
T* backup;
};

template<class T>
CanBackup<T>::C anBackup()
: backup(NULL)
{
}

template<class T>
CanBackup<T>::~ CanBackup()
{
if(backup)
delete backup;
There is no need to test 'backup' before deleting. "delete NULL;" is
a NOP.
}

template<class T>
void CanBackup<T>::M akeBackup()
{
backup = (T*)Clone();
Why do you need to cast? I would rather expect either 'Clone' to
return a T* or 'backup' to be of type 'CanBackup*'. See below.
}

template<class T>
void CanBackup<T>::R estoreBackup()
{
*((T*)this) = *backup;
This is utterly dangerous. Who told you that it's even going
to work? Casting 'this' like that is an invitation for a big
trouble.

If you make 'backup' to be of type 'CanBackup*', then you can
use 'dynamic_cast<T *>' here and only assign if you get non-null
ponter back...
}

class A : public CanBackup<A{
public:
A();
~A();
You don't need those.
A* Clone();
^^^^^^^^^^^
This should probably be private.
int x;
};

A::A() {}
A::~A() {}

A* A::Clone()
{
return new A(*this);
}

// Should print: 3 5 3
// Actually prints: 3 5 5
Of course. You're using some very dangerous constructs.
int main() {
A foo;
foo.x = 3;
std::cout << foo.x << std::endl;
foo.MakeBackup( );
foo.x = 5;
std::cout << foo.x << std::endl;
foo.RestoreBack up();
std::cout << foo.x << std::endl;
}
So, I'd rewrite it as

template<class T>
class CanBackup {
public:
CanBackup() : backup(NULL) {}
virtual ~CanBackup() { delete backup; }
void MakeBackup();
void RestoreBackup() ;

virtual CanBackup* Clone() = 0;

private:
CanBackup* backup;
};

template<class T>
void CanBackup<T>::M akeBackup()
{
backup = Clone();
}

template<class T>
void CanBackup<T>::R estoreBackup()
{
T* that = dynamic_cast<T* >(backup);
T* self = dynamic_cast<T* >(this);
if (that && self)
*self = *that;
}

class A : public CanBackup<A{
public:
CanBackup<A>* Clone();
int x;
};

CanBackup<A>* A::Clone()
{
return new A(*this);
}

Now, for me this (along with your 'main') will print 3 5 3.
There is still some protection you need to do, probably, to ensure
that nobody does this:

class A { ... };
class B : public CanBackup<A{ ...

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 12 '06 #2
k0*****@gmail.c om wrote:
Problem:

I have a properties dialog. X objects build the dialog, but a subclass
of X, such as Y, can add more options to the dialog for Y specific
properties. I would like to write code for the dialog that creates a
backup of the current object when the dialog pops up, and sets the
current modified object to the backup when the user clicks cancel (or
discards the backup if the user clicks OK). X already has a Clone
method.

(I realize this way of making backups isn't always practical for large
objects, but the ones I'm dealing with are fairly lightweight)
[snip]

Consider using standard serialization/unserialization techniques. See
these FAQs:

http://www.parashift.com/c++-faq-lit...alization.html

and this handy library:

http://boost.org/libs/serialization/doc/index.html

Cheers! --M

Aug 12 '06 #3
Victor Bazarov wrote:
k0*****@gmail.c om wrote:
0. Simply write the code using X pointers. Problem: Then only the X
members get set because the assignment operator can't be virtual.

Says who? Have you tried making it virtual? Did it not work?
Sorry, I should have explained more. The idea is that this can be used
with the compiler generated assignment operator, which is not virtual.
Now that I think about it the Clone method is probably not needed do to
the template either...
>
There is no need to test 'backup' before deleting. "delete NULL;" is
a NOP.
I'd read so much stuff telling me not to free() NULL pointers I thought
this carried over ;P Thanks :)
>
template<class T>
void CanBackup<T>::M akeBackup()
{
backup = (T*)Clone();

Why do you need to cast? I would rather expect either 'Clone' to
return a T* or 'backup' to be of type 'CanBackup*'. See below.
Without it the code doesn't compile. You can't implicitly cast
CanBackup<X*to X*.
>
template<class T>
void CanBackup<T>::R estoreBackup()
{
*((T*)this) = *backup;

This is utterly dangerous. Who told you that it's even going
to work? Casting 'this' like that is an invitation for a big
trouble.

If you make 'backup' to be of type 'CanBackup*', then you can
use 'dynamic_cast<T *>' here and only assign if you get non-null
ponter back...
I've rewritten it to this:

dynamic_cast<T& >(*this) = *backup;

This way an exception gets thrown because you can't have a NULL
reference.
>
A* Clone();
^^^^^^^^^^^
This should probably be private.
Good point :P
// Should print: 3 5 3
// Actually prints: 3 5 5

Of course. You're using some very dangerous constructs.
Whoops, it does actually print 3 5 3. I forgot to remove those old
comments from before I had it working :)

Aug 12 '06 #4
k0*****@gmail.c om schrieb:
Victor Bazarov wrote:
>k0*****@gmail.c om wrote:
>>template<clas s T>
void CanBackup<T>::M akeBackup()
{
backup = (T*)Clone();
Why do you need to cast? I would rather expect either 'Clone' to
return a T* or 'backup' to be of type 'CanBackup*'. See below.

Without it the code doesn't compile. You can't implicitly cast
CanBackup<X*to X*.
You can't even _explicitly_ cast CanBackup<X*to X* and get a sane result.
And you cast a CanBackup<X*>* to X*, what makes it even worser.

What makes you think that this should work?

--
Thomas
Aug 12 '06 #5
k0*****@gmail.c om wrote:
>
>>There is no need to test 'backup' before deleting. "delete NULL;" is
a NOP.


I'd read so much stuff telling me not to free() NULL pointers I thought
this carried over ;P Thanks :)
Calling free() with a null pointer is safe.

--
Ian Collins.
Aug 12 '06 #6

Thomas J. Gritzan wrote:
k0*****@gmail.c om schrieb:
Victor Bazarov wrote:
k0*****@gmail.c om wrote:
template<cla ss T>
void CanBackup<T>::M akeBackup()
{
backup = (T*)Clone();
Why do you need to cast? I would rather expect either 'Clone' to
return a T* or 'backup' to be of type 'CanBackup*'. See below.
Without it the code doesn't compile. You can't implicitly cast
CanBackup<X*to X*.

You can't even _explicitly_ cast CanBackup<X*to X* and get a sane result.
And you cast a CanBackup<X*>* to X*, what makes it even worser.

What makes you think that this should work?
Well, that it does work. I cast CanBackup<X>* to X*, not CanBackup<X*>*
to X* (note only one asterisk in the first). In practice X should
always be a subclass of CanBackup<X(tha t's intended usage, I could
probably add safeguards to enforce this).

Aug 13 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
12147
by: Cristina | last post by:
Hallo i am a beginner into Oracle Technologies.I would like to make backup of my database,but i dont know how.Is there tools?Can i schedule the backup plan? thanks Cristina
1
1757
by: Leader | last post by:
Hi, I want to take backup of database logfile periodically and automatically. What should i do then..... Thanks Hoque
3
2329
by: anuke | last post by:
Hi there, I use shared space MSSQL server in my hosting server. And I can't backup my DB to my remote server. Please help how can I do it. Thank you
3
2404
by: Colin Finck | last post by:
Hello! I need to backup a MySQL database (MySQL 4.0). But it is on a shared-hosting web server and so I don't have direct server access. I also have no phpMyAdmin installed. How can I backup the database? I think it is possible with PHP (version 5.0.2 is installed on the web server) to create a file with SQL commands which restore the data, but what is the easiest way to do it? Thanks in advance!
5
7966
by: Kevin | last post by:
Can anyone recommend the easiest way to get a full copy of a database from one server to another. The servers are not part of the same organization or network. I have received a backup of the database created with enterprise manager but am unable to restore it into a database of the same name on my server. Thanks, Kevin
5
7087
by: Jim | last post by:
Hello, I have a broken server that we are going to be moving off to a new server with a new version of DB2 but here is what I have right now: RedHat 7.0 (2.2.24smp) DB2 v6.1.0.40 I am getting this error when I try to run the command 'db2 "backup database dbname online to /opt/BACKUP"' on my 3 databases: SQL1042C An unexpected system error occurred. SQLSTATE=58004
6
3350
by: Eric Herber | last post by:
I've a question regarding db2 (V8.1) and database backups going to a storage manager like TSM for example. As I can see in the storage manager if I backup the complete database over the TSM API (no tablespace backups) the backup images is stored as a single backup object. Later I will be able to restore the complete database from this image and I will also be able to restore single tablespaces from this backup image as long as I...
14
14321
by: vince | last post by:
Can I add (append) to an xml file that already contains a serialized object, and be able to deserialize to either or both objects from the same file...??? How is this done...?? thanks, vince
6
7723
by: michael.spoden | last post by:
Hi, how can I fix lock-waits during an online backup? Is an online backup in DB2 V8.2 not realy online? I'm using DB2 V8.2 Fixpak 15 on Linux. The command to perform the backup is: db2 backup db BPEDB online to / var/tmp During the backup the application hangs on just one table
0
10620
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10369
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10372
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9187
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7650
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6877
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5682
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4329
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3851
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.