-
enum in a class
hello, I need to compile this code but some errors:
Code:
class P {
public:
enum Type { type1, type2 };
P(Type t) : _d1(t) {}
D _d1;
};
class D {
public:
D(P::Type t) { }
};
How come, please?
-
You can't declare a data member of type D inside P before you've declared D! You need to use a forward declaration and move the constructor of P outside its class, after the declaration of D:
Code:
class D;
class P {
public:
enum Type { type1, type2 };
P(Type t);
D *_d1;
};
class D {
public:
D(P::Type t) { }
};
P::P(Type t) { _d1=new D(t);}
Danny Kalev
-
I guees the costructor can go in a cpp too....
I do this for put the enum inside a class for not do it global; is it a good choice?
-
You can't define the constructor inside the P class declaration because class D hasn't been declared yet at that point. That's why I had to move the constructor outside P, after D.
Putting the enum inside the class can be a good design choice or a bad design choice. It depends on who's using that enum (which classes, that is) and how it affects the overall design. I suspect that in this example, the enum should have been declared outside the class because two unrelated classes use it, so why hide it from D?
Danny Kalev
-
 Originally Posted by Danny
You can't define the constructor inside the P class declaration because class D hasn't been declared yet at that point. That's why I had to move the constructor outside P, after D.
Putting the enum inside the class can be a good design choice or a bad design choice. It depends on who's using that enum (which classes, that is) and how it affects the overall design. I suspect that in this example, the enum should have been declared outside the class because two unrelated classes use it, so why hide it from D?
to be sincer "P" and "D" are not good names; I can say that P "contains" D (in fact composition).....see this:
Code:
class Trasformation;
class Cleaning;
class Processing {
static const enum TypeofTrasformation {trasf1, trasf2, trasf3 };
static const enum TypeofCleaning { clean1, clean2, clean3 };
Trasformation* _t;
Cleaning* _c;
};
Processing::Processing (TypeofTrasformation t, TypeofCleaning c) : _t(new Trasformation(t), _c( new Cleaning(c) ) { }
class Trasformation {
Processing::TypeofTrasformation _typeT;
public:
Trasformation(Processing::TypeofTrasformation t) : _type(t) { }
}
class Cleaning {
Processing::TypeOfCleaning _typeC
public:
Cleaning(Processing::TypeOfCleaning c) : _c(c) { }
}
Is this ok? I alsways think that put something out of a class isn't a good OO design....
-
This isn't containment. When P contains D, it means that D is a nested class defined inside P. When P contains a D object, it means that P contains an instance of D (and object of D that is). Neither of these applies here because you can't have D as a member of P. You can only store a pointer to D or a reference to D inside P. This is called association, not containment.
Again, it's hard to tell whether it's good or bad without looking into the application in question and the relationships between the two classes. However, as a general guideline, using a type field (that tells what the exact type of an object is) isn't exactly through and through OOD. Instead, you should consider inheritance, virtual functions and dynamic_cast. After all, a type field restricts your application to types that are known at compile-time, and that means you need to change several code modules when a new class is added.
Last edited by Danny; 08-20-2008 at 04:05 PM.
Danny Kalev
-
Sorry, could you advice me about this programming problem?
Code:
class Trasformation;
class Cleaning;
class Processing {
MyObj* _myobj; // <---------------------------------
public:
static const enum TypeofTrasformation {trasf1, trasf2, trasf3 };
static const enum TypeofCleaning { clean1, clean2, clean3 };
Trasformation* _t;
Cleaning* _c;
};
Processing::Processing ( MyObj* mo, TypeofTrasformation t, TypeofCleaning c) : _myobj( mo ), _t(new Trasformation(t), _c( new Cleaning(c) ) { }
class Trasformation {
Processing::TypeofTrasformation _typeT;
public:
Trasformation(Processing::TypeofTrasformation t) : _type(t) { }
void compute() { /*how access to _myobj here ? */ } //<-------------
}
class Cleaning {
Processing::TypeOfCleaning _typeC
public:
Cleaning(Processing::TypeOfCleaning c) : _c(c) { }
void compute() { /*how access to _myobj here ? */ } //<-------------
}
-
Why do you need top know the exact type of the transformation object? You can make it a polymorphic class instead and define a virtual function "dosomething" or whatever which every class derived from it overrides. Thsi way you will not need to pick the exact type. Also, what's the purpose of the cleanup class? You can simply use a destructor for that purpose, particualraly the destructor of the transformation object -- after all, that's the object that knows what type of activity has taken place.
Danny Kalev
-
Hello, I'm a bit confuse about how design it!
Cleaning class must do some "changing" on the datas( _myobj;, that points to a vector); my Idea is that Processing can be a Trasformation (that can do 3 type of trasformation, eg one can be data normalization) and cleaning (3 type of cleaning, eg one kind of clean is delete some elements from _myobj;); tipically, processing consists of both them; said that what type of design do you suggest, please?
-
design will vary based on what you actually do in this function, how often you need to do it, etc. If you do it often, it needs to be efficient for example.
Some ideas you might use assuming you need to favor speed (this cleaning / processing is done a lot) :
Use lazy delete. Make whatever class you store have a boolean that means deleted if its true (example), so when you process, print, or do stuff you can 1) reuse the deleted locations instead of creating more space or other such things and 2) its fast to delete stuff and fast enough to ingore deleted items in a typical iterative algorithm (do you use anything fancy like binary search? Lazy deletes can make trouble (extra work, performance hits) in some algorithms.
2) use double buffer concept: This means that you have an active buffer and a working buffer. You process from active into working, swap the pointers (active becomes working, working becomes active) when done. This wastes space but gives you good performance, lets you drop deleted items (works great with lazy delete for example), lets you use non linear algorithms to post process the list (orig list still exists so you can do what you like post processing it to make the new data ???). You can also use this sort of concept to have 1 buffer the user can see while you post process it ahead of time or in a thread to use idle time. Then when the user tells you to post process, its nearly done, just check for any changes in his buffer and your copy. Of course that depends on your algorithm, but for many things you can do this to have snappy response time instead of a sudden 20 second processing wait time...
3) seperate the tasks. Cleanup is very differnt from processing, and should not be lumped up like this under most normal designs.
Similar Threads
-
Replies: 27
Last Post: 02-11-2016, 06:29 AM
-
By Osiris43 in forum .NET
Replies: 1
Last Post: 08-04-2006, 12:15 PM
-
Replies: 5
Last Post: 01-15-2006, 08:10 PM
-
By none_none in forum Java
Replies: 17
Last Post: 04-28-2005, 03:00 PM
-
Replies: 5
Last Post: 10-17-2002, 01:58 PM
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Development Centers
-- Android Development Center
-- Cloud Development Project Center
-- HTML5 Development Center
-- Windows Mobile Development Center
|