-1

So for school in c++ part of a project is to make a single constructor that can construct a node with a data value, a node with a data value AND a left child, or a node with a data value AND left child AND right child. I've tried to Google it and I'm sure its a simple convention, I just haven't been able to find anything.

How do you write a constructor that uses parameters if they are there, and ignores them otherwise?

something like:

public TreeNode(T data, #TreeNode left, #TreeNode right)

where the # denotes "might not be there"

sampathsris
  • 21,564
  • 12
  • 71
  • 98
mday99
  • 7
  • 6
  • You are probably looking for [constructor overloading.](http://stackoverflow.com/questions/7330296/constructor-overloading-in-c). If you check the answer in the link you will see that the class may have multiples constructors with different parameters. – wendelbsilva Oct 21 '14 at 21:41
  • 1
    More like default-values. (Use `= initializer`) at the end of the argument. BTW: You can only default an argument if there is no non-defaulted argument following. – Deduplicator Oct 21 '14 at 21:41
  • Like in python? He can always initialize `left` and/or `right` to null in the others constructors. Although, I dont know if thats a good practice. – wendelbsilva Oct 21 '14 at 21:42
  • @wendelbsilva If those are truly optional (and in a tree they *must* be -- if child nodes are required then you can only have infinite trees!) then using a null pointer or some other sentinel "no value" value is not only correct, but is the *only way* to accomplish this task. – cdhowie Oct 21 '14 at 21:56

2 Answers2

3

You have two options: constructor overloading, or default values for the optional parameters.

I am going to assume that the left and right constructor arguments should actually be pointers to nodes since you are building a tree. (I would suggest using std::unique_ptr here but I'm going to just use raw pointers in this answer since it's not important to the answer to this particular question. However, I would strongly suggest investigating std::unique_ptr since it will mean you won't need a custom destructor to delete child nodes; the smart pointer destructor will take care of that for you.)

Constructor overloading

Simply define multiple constructors that take all of the combinations you need:

public:
    explicit TreeNode(T data);
    TreeNode(T data, TreeNode * left);
    TreeNode(T data, TreeNode * left, TreeNode * right);

You need to implement each constructor separately, but note that you can call one constructor from another using the constructor's initializer list.

Default values

public:
    explicit TreeNode(T data, TreeNode * left = nullptr, TreeNode * right = nullptr);

(Substitute NULL for nullptr if you are not using C++11.)

In this case, left and right are optional parameters that will be "filled in" using the supplied defaults if they are omitted. (Note that you cannot omit only left; if you omit left you must also omit right.)

When actually implementing the constructor you do not need to specify the default values again:

TreeNode::TreeNode(T data, TreeNode * left, TreeNode * right)
{
    // ...
}

In both cases you will be able to call the constructor with one, two, or three arguments.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • 1
    Actually, for minimal dependencies, use plain `0`, neither `NULL` (needs a header) nor `nullptr` (needs C++11). – Deduplicator Oct 21 '14 at 21:51
  • @Deduplicator 0 isn't very semantic; in my own code I would much prefer to use something symbolic instead. – cdhowie Oct 21 '14 at 21:53
  • Ah, well. Where it is blatantly obvious that the `0` is a nullpointer-constant, I consider using anything else excessively loquacious. A matter of taste. Anyway +1. – Deduplicator Oct 21 '14 at 21:57
  • @Deduplicator That is a truly fantastic word. – cdhowie Oct 21 '14 at 22:00
  • Thanks for your response. Since the assignment requires a single constructor, it seems default values will work great. – mday99 Oct 21 '14 at 23:47
3

In C++, you can provide a default for any function-argument you want, as long as it is not followed by arguments without defaults:

Needs 3 arguments:

int f(int a, int b, int c);

Needs 2 arguments, the third is defaulted if not supplied:

int g(int a, int b, int c = f(1,2,3));

Illegal: Cannot provide a default for argument 2, as an argument without default follows:

int h(int a, int b = 0, int c);

Be aware that a constructor which can be called with only one argument is a user-defined conversion.
So define it explicit unless you are really sure what you are doing.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118