简体   繁体   中英

C++ Constructors, Constants, Inheritance and Avoiding Repetition

so I've been learning C++ for a few weeks now but I'm having a bit of trouble:

Class Tool
{
public:
    Tool(const float maxCarried = 1):maxAmountCarried(maxCarried){}
    virtual void Use() = 0;
    /* ... */
}

Class CuttingTool: public Tool
{
public:
    CuttingTool(const float maxCarried):Tool(maxCarried){}
    virtual void Use(){ /* ... */ }
    /* ... */
}

Class Saw: public CuttingTool
{
public:
    Saw(const float maxCarried):CuttingTool(1){}
    virtual void Use(){ /* ... */ }
    /* ... */
}
Class Scissors: public Fruit
{
public:
    Scissors(const float maxCarried):CuttingTool(2){}
    virtual void Use(){ /* ... */ }
    /* ... */
}

A few things to note:

  • I'm trying to make a big database of 'Tools'.
  • I never change the value of 'maxAmountCarried' so I've set it to const.
  • Memory/performance is important because I have a huge vector of Tools.

The problem lies within the fact that I have to keep writing:

ClassName(const float maxCarried):BaseClass(maxCarried){}

It's really tedious, moreover, I worry that if I were to add a new const value I would have to repeat the process all over again (problem when you have 50 classes inheriting from Food :S).

I feel as though I've designed this poorly. Is there a way to avoid repeating the same line of code over and over again or do I just have to suck it up and deal with it?

Thanks in advance.

If your only concern is the repeating initialization list you could use a macro like this:

#define DEFAULT_CONSTRUCTOR(Child, Parent) Child(float max) : Parent(max) {}

and use it like so:

class Saw : public CuttingTool
{
public:
    DEFAULT_CONSTRUCTOR(Saw, CuttingTool) {}
};

You can extend this idea and do something like that:

#define BEGIN_CLASS(Child, Parent) class Child : public Parent { \
                                      public: \
                                         Child(float max) : Parent(max) {}

#define END_CLASS };

and declare your classes:

BEGIN_CLASS(Scissors, Tool)
   void cut_through_paper() {}   // specific method for scissors
END_CLASS

Note that there is no point of using const float as a parameter since you can't change arguments passed by value anyway. You might however want to use const float& to pass an argument by reference, and that will make sense if size of float is bigger than the size of a pointer in your specific platform.

If you never change you max value, you can make it static and share it between all tool instances:

class Tool
{
protected:
   static const float _max;
public:
   Tool() {}
};
const float Tool::_max = 0;

If you'd like to be able to change max value only once (say at the begining of your program, you can add a static function:

static void globalMax(float max) { Tool::_max = max; }

and use it where appropriate:

int main() {
   Tool::globalMax(5);
   ...
   ...
}

Note that you should remove the const from the _max declaration.

Finally, if performance is an issue, you probably need to rethink your design and maybe go with something else (templates maybe?)

Hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM