![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Professional Programmer
Join Date: Jan 2007
Location: Cape Town
Posts: 291
Rep Power: 2
![]() |
OOP design question
Hey!
I have a question about designing an OOP system: Say we have a base class Base, and we derive a class Derived from Base. In the copy constructor, of Derived, one would have to call the methods that operate on the Base classes data, i.e class Base {
public:
Base() {
a = 99;
b = 101;
c = 2232;
}
Base(const Base &src) {
a = src.a;
b = src.b;
c = src.c;
}
~Base() {}
int GetA() { return a; }
void SetA(int _a) { a = _a; }
int GetB() { return b; }
void SetB(int _b) { b = _b; }
int GetC() { return c; }
void SetC(int _c) { c = _c; }
private:
int a;
int b;
int c;
};
class Derived : public Base {
public:
Derived() : Base() {
data = 34334;
}
Derived(const Derived &src) {
SetA(src.GetA());
SetB(src.SetB());
SetC(src.SetC());
data = src.data;
}
~Derived() {}
int GetData() { return data; }
void SetData(int d) { data = d; }
private:
int data;
};now my question is; is it ok to make the data of Base protected, so i can directly access them in the copy constructor? like this: Derived(const Derived &src) {
a = src.a;
b = src.b;
c = src.c;
}i feel this is not a safe method? since any class taht derives from Base can access this data - when i want to keep it unaccessible... is there an easier way to copy construct? or do I have to call Base's public methods to do this? please help! thanks! ![]() |
|
|
|
|
|
#2 |
|
Hobbyist Programmer
Join Date: Jan 2006
Location: UK
Posts: 215
Rep Power: 3
![]() |
well it kind of makes sense for derived classes to have access to ones base classes protected attributes. I would consider a review of what you have designed.
that said however, you could look into a friend class, it seems to be what you are looking for: http://www.codersource.net/cpp_tutorial_friend.html This will allow one class to have access to the private data of the class that declared it a friend. |
|
|
|
|
|
#3 |
|
Professional Programmer
Join Date: Jan 2007
Location: Cape Town
Posts: 291
Rep Power: 2
![]() |
Hey Seif!
Thanks for the reply! Mmm well I suppose its ok... Just wondered what some would have to say about hte issue... It seems better to use protected members than to declare the class as a friend. It breaks the whole OOP structure... I guess? |
|
|
|
|
|
#4 |
|
Resident Grouch
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jun 2005
Posts: 6,453
Rep Power: 10
![]() |
It really depends on what the classes are for and what you're actually trying to accomplish. Look at your getters and setters. They don't really protect your data. They allow the user to set any value that user wishes, but they only force him to do that in a roundabout way. That's obfuscation, not protection.
The purpose of a setter is to protect the data from being improperly set. You apparently have no rules to break, so there's nothing to protect. If, on the other hand, b should only be in the range 0-9, your setter can enforce that, whereas direct access cannot. Once you've defined a useful setter, then you need a getter because you've shut the member down for direct access. If you want to break that protection for any other class, then you have to know that unconstrained actions by that other class can't break your functionality. You're the designer. Only you know, unless you tell. Relaxing that protection does not "break the OOP." Your object is still an object. It only breaks (possibly) the integrity of that object, functionally speaking. Consider the accelerator on your car. It allows a specific range of inputs for fuel flow. Internal methods operate on that range to add a specific range of airflow to mix with it. That doesn't keep an unprotected member, say the butterfly valve, from being farbled with independently, thus modifying the intended behavor. Should you leave the butterfly valve out in the open, protect it somewhat with an aircleaner, or put the whole assembly in a welded-closed box? Your call.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code. Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers Last edited by DaWei; May 15th, 2007 at 10:23 AM. |
|
|
|
|
|
#5 |
|
Professional Programmer
Join Date: Jan 2007
Location: Cape Town
Posts: 291
Rep Power: 2
![]() |
Hey DaWei!
Thanks for the explanation - that was very helpful! Of course, it all makes sense, the user can never access private or protected data, only public, so, in my case, the classes that the client will operate on can access/modify the Base class data, but not directly, only through the public member functions passed on through the hierarchy. So obviously its ok to make the data protected for all the derived classes - since it makes copy constructing much easier... Thanks again! ![]() |
|
|
|
|
|
#6 |
|
Professional Programmer
Join Date: May 2006
Location: Maryland, USA
Posts: 306
Rep Power: 3
![]() |
I am really surprised no one gave the OP the answer he was actually looking for the "right" way to copy construct a derived class is to call the copy constructor of the super class like so:
cpp Syntax (Toggle Plain Text)
__________________
Robotics @ Maryland AUV Team - Software Lead |
|
|
|
|
|
#7 |
|
Programming Guru
![]() Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,223
Rep Power: 5
![]() |
Close, Game_Ender.
A preferable way would often be; // Base constructor within class Base
Base(const Base &src) : a(src.a), b(src.b), c(src.c)
{
}
// Derived constructor within class Derived
Derived(const Derived &src) : Base(src), data(src.data)
{
}One additional rule of thumb is also that, if a class needs a hand-rolled copy constructor, it also needs a hand-rolled assignment operator. In practice, if assumption (1) is true, then assumption (2) is rarely true. In the particular example, it is not actually necessary to hand-roll a copy constructor for either class Base or class Derived: the compiler generated versions work fine. int is a basic type. So I would actually implement the classes in rwm's first example as; class Base {
public:
Base() {
a = 99;
b = 101;
c = 2232;
}
// look Ma: no hand-rolled copy constructor
~Base() {}
int GetA() { return a; }
void SetA(int _a) { a = _a; }
int GetB() { return b; }
void SetB(int _b) { b = _b; }
int GetC() { return c; }
void SetC(int _c) { c = _c; }
private:
int a;
int b;
int c;
};
class Derived : public Base {
public:
Derived() : Base() {
data = 34334;
}
// look Ma: no hand-rolled copy constructor
~Derived() {}
int GetData() { return data; }
void SetData(int d) { data = d; }
private:
int data;
}; |
|
|
|
|
|
#8 |
|
Professional Programmer
Join Date: Jan 2007
Location: Cape Town
Posts: 291
Rep Power: 2
![]() |
hey guys I already know how to copy construct - sometimes i just miss stuff hwne i type out - im at work - always on the rush! but thanks for the replies - was intersting read!
|
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| object design question | rwm | C++ | 21 | May 11th, 2007 7:11 AM |
| The Black Art of Video Game Console Design | lostcauz | Book Reviews | 0 | Apr 26th, 2006 7:31 PM |
| Attitudes | Oddball | Coder's Corner Lounge | 29 | Mar 18th, 2006 9:34 PM |
| How to post a question | nnxion | C++ | 10 | Jun 3rd, 2005 11:53 AM |
| How to post a question | nnxion | C | 0 | Jun 3rd, 2005 8:55 AM |