tags:

views:

163

answers:

8
A: 

It all depends:

  1. An internal struct would only be useful if you need to organize VERY many items. And if this is the case, you ought to reconsider your design.
  2. An external struct would be useful if it will be shared with other instances of the same or different classes. (A model, or data object class/struct might be a good example)
  3. Is only ever advisable for trivial, throw-away code.
  4. This is the standard way of doing things but it all depends on how you'll be using the class.
Paul Sasik
+2  A: 

if i had to choose one of the four solutions you listed: private class within a class.

in reality: you probably have duplicate code which should be reused, and your class should be reorganized into smaller, more logical and reusable pieces. as GMan said: refactor your code

Justin
A: 

I don't see any benefit whatsoever to making a separate structure to hold the parameters. The class is already a struct - if it were appropriate to pass parameters by a struct, it would also be appropriate to make the class members public.

There's a tradeoff between public members and Set/Get functions. Public members are a lot less boilerplate, but they expose the internal workings of the class. If this is going to be called from code that you won't be able to refactor if you refactor the class, you'll almost certainly want to use Get and Set.

Mark Ransom
A: 

Sounds like this could be a job for a template, the way you described the usage.

template class FunctionOptimizer <typename FUNCTION, typename METHOD, 
    typename PARAMS>

for example, where PARAMS encapsulates simple optimization run parameters (# of iterations etc) and METHOD contains the actual optimization code. FUNCTION describes the base function you are targeting for optimization.

The main point is not that this is the 'best' way to do it, but that if your class is very large there are likely smaller abstractions within it that lend themselves naturally to refactoring into a less monolithic structure.

However you handle this, you don't have to refactor all at once - do it piecewise, starting small, and make sure the code works at every step. You'll be surprised how much better you quickly feel about the code.

Steve Townsend
A: 

Assuming that the configuration options apply only to this class, use private variables that are manipulated by public functions with meaningful function names. SetMaxInteriorAngle() is much better than SetMIA() or SetParameter6(). Having getters and setters allows you to enforce consistency rules on the configuration, and can be used to compensate for certain amounts of change in the configuration interface.

If these are general settings, used by more than one class, then an external class would be best, with private members and appropriate functions.

Public data members are usually a bad idea, since they expose the class's implementation and make it impossible to have any guaranteed relation between them. Walling them off in a separate internal struct doesn't seem useful, although I would group them in the list of data members and set them off with comments.

David Thornley
A: 

I have used the following approach to organize the members in my C++ classes:

class AnyClass
{
    public:
        AnyClass ();                    // 1. default constructor
        AnyClass (const AnyClass& rAnyClass);       // 2. copy constructor
        AnyClass (int iRows, int iColumns);     // customized constructor
        virtual ~AnyClass ();               // 3. destructor
        AnyClass& operator= (const AnyClass& rAnyClass);// 4. assigment operator

        AnyClass& operator+= (const AnyClass& rAnyClass);//composed assigment operators

        bool operator==(const AnyClass& rAnyClass); //5. equals operator
        bool operator!=(const AnyClass& rAnyClass); //6. not equals operator

        AnyClass operator+ (const AnyClass& rAnyClass) const;
        friend AnyClass operator+ (const AnyClass& rAnyClass, double dNum);//binary operators

        AnyClass operator- () const;                
        AnyClass operator- (const AnyClass& rAnyClass) const;       //unary operators

        friend AnyClass operator/ (const AnyClass& rAnyClass, double dNum);

        double operator! ();
        AnyClass operator~ ();

        ComponentClass operator[] (int iIndex) const;       //index operators

        ComponentClass GetComponent (int iIndex) const;        //methods

private:
       //private data, from basic to complex    
int _iRows;
    int _iColumns;
    ComponentClass* _pComponentClass;
};

Note: This is based in the High Integrity Coding Standard Manual.

ArceBrito
This example does not show how to organize a lot of data members. Also, link?
jmucchiello
@jmucchiello: There is a principle in Object Oriented Design, Single Responsibility Principle, that states for: A class should have one, and only one, reason to change. Lots of members in a class could indicate a poor object oriented design.
ArceBrito
the comments in your example aren't particular helpful. Anyone reading can interpret `AnyClass ();` is the default constructor, likewise `~AnyClass();` is the destructor. Comments should describe the why, not the what.
Sam Miller
@Sam Miller: what I was trying is to show the minimal members a class should have according to the HIGH·INTEGRITY C++ CODING STANDARD MANUAL. Guideline 3.1.13: Verify that all classes provide a minimal standard interface against a checklist comprising: a default constructor; a copy constructor; a copy assignment operator and a destructor.
ArceBrito
A: 

If your class is BIG, then your class is BAD. A class should respect the Single Responsibility Principle , i.e. : A class should do only one thing, but should do it well. (Well "only one" thing is extreme, but it should have only one role, and it has to be implemented clearly).

Then you create classes that you enrich by composition with those single-role little classes, each one having a clear and simple role.

BIG functions and BIG classes are nest for bugs, and misunderstanding, and unwanted side effects, (especially during maintainance), because NO MAN can learn in minutes 700 lines of code.

So the policy for BIG classes is: Refactor, Composition with little classes targetting only at what they have do.

Stephane Rolland
Having a lot of parameters doesn't mean the class is big. The class might do one thing, but require many parameters.
Adrian McCarthy
@Adrian McCarthy , I will answer you just a quotation: "If your function takes 10 parameters, you have most probably forgotten one".
Stephane Rolland
but I agree with you, as long as it does one precise role.
Stephane Rolland
+1  A: 

First, I'd partition the members into two sets: (1) those that are internal-only use, (2) those that the user will tweak to control the behavior of the class. The first set should just be private member variables.

If the second set is large (or growing and changing because you're still doing active development), then you might put them into a class or struct of their own. Your main class would then have a two methods, GetTrackingParameters and SetTrackingParameters. The constructor would establish the defaults. The user could then call GetTrackingParameters, make changes, and then call SetTrackingParameters. Now, as you add or remove parameters, your interface remains constant.

If the parameters are simple and orthogonal, then they could be wrapped in a struct with well-named public members. If there are constraints that must be enforced, especially combinations, then I'd implement the parameters as a class with getters and setters for each parameter.

ObjectTracker tracker;  // invokes constructor which gets default params
TrackerParams params = tracker.GetTrackingParameters();
params.number_of_objects_to_track = 3;
params.other_tracking_option = kHighestPrecision;
tracker.SetTrackingParameters(params);
// Now start tracking.

If you later invent a new parameter, you just need to declare a new member in the TrackerParams and initialize it in ObjectTracker's constructor.

Adrian McCarthy