making the leap from java to c++

Hello all,

As the topic says I'm very new to c++, but I have some experience with java.
To start learning c++ I had the (not very original) idea of making a simple command line calculator.
What I'm trying to do is store the numbers and operators in a binary tree.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <iostream>
using namespace std;

class Node
{
  bool leaf;
  double num;
  char oper;
  Node* pLNode;
  Node* pRNode;

public:

  Node(double n)
  {
    num = n;
    leaf = true;
    pLNode = 0;
    pRNode = 0;
  }

  Node(char o, Node lNode, Node rNode)
  {
    oper = o;
    pLNode = &lNode;
    pRNode = &rNode;
    leaf = false;
  }

  bool isLeaf()
  {
    return leaf;
  }

  double getNumber()
  {
    return num;
  }

  char getOperator()
  {
    return oper;
  }

  Node* getLeftNodePointer()
  {
    return pLNode;
  }

  Node* getRightNodePointer()
  {
    return pRNode;
  }

  //debug function
  void dump()
  {
    cout << endl << "**** Node Dump ****" << endl;
    cout << "oper: " << oper << endl;
    cout << "num: " << num << endl;
    cout << "leaf: " << leaf << endl;
    cout << "*******************" << endl << endl;
  }

};

class CalcTree
{
  Node* pRootNode;
  Node* pCurrentNode;
public:

  Node* getRootNodePointer()
  {
    return pRootNode;
  }

  Node* getCurrentNodePointer()
  {
    return pCurrentNode;
  }

  void setRootNode(Node node)
  {
    pRootNode = &node;
  }
 
  void setCurrentNode(Node node)
  {
    pCurrentNode = &node;
  }

  double calculateTree()
  {
    return calculateTree(pRootNode);
  }

private:

  double calculateTree(Node* nodePointer)
  {
    if(nodePointer->isLeaf())
    {
      return nodePointer->getNumber();
    }
    else
    {
      Node* leftNodePointer = nodePointer->getLeftNodePointer();
      Node* rightNodePointer = nodePointer->getRightNodePointer();
      char oper = nodePointer->getOperator();

      if(oper == '+')
      {
	return calculateTree(leftNodePointer) + calculateTree(rightNodePointer);
      }
      else if(oper == '-')
      {
	return calculateTree(leftNodePointer) - calculateTree(rightNodePointer);
      } 
      else if(oper == '*')
      {
	return calculateTree(leftNodePointer) * calculateTree(rightNodePointer);
      }
      else if(oper == '/')
      {
	return calculateTree(leftNodePointer) / calculateTree(rightNodePointer);
      }
    }
  }
};

int main(int argc, char* argv[])
{
  CalcTree tree;
  tree.setRootNode(Node('+', Node(1), Node(534)));
  cout << tree.calculateTree() << endl;
  return 0;
}


I've got a couple of questions about this code:

1. This compiles but does not do what's intended. It seems that after tree.setRootNode(Node('+', Node(1), Node(534))); in main, the rightnode is initialized properly but the leftnode isn't. Compiling and running this prints out 534 for me (gcc, freebsd). What is wrong here?

2. It seems in c++ people prefer to define members of a class outside the class, like
1
2
3
4
5
6
7
class A
{
public:
  void member();
};

A :: member(){std::cout << "Hello world" << std::endl;}


why is that?

3. I'd very much like some pointers on c++ conventions (naming, indenting etc.)

4. I'm used to coding java with eclipse. Atm I'm using emacs for learning c++. Can someone advise me on a good (free) c++ ide, or should I stfu and stick with emacs like a real man? :)


Last edited on
I like Microsoft Visuall C++ Express, but that's just personal opinion. I believe there is an article on the topic.

Edit: Here's the link: http://cplusplus.com/forum/articles/7263/
Last edited on
In Java, all objects are held by reference (and reference counted) and you instantiate them by calling new.

In C++, objects can be created just by declaring them, these are generally greated on the stack. Objects can be created on the heap (as in Java) by instantiating them by calling new (as in Java). The two cannot be mixed.

So, in your code:
1
2
3
4
5
6
7
8
9
10
  Node(char o, Node lNode, Node rNode)
  {
    oper = o;
    pLNode = &lNode;
    pRNode = &rNode;
    leaf = false;
  }

  //...
  Node('+', Node(1), Node(534));


Node('+', Node(1), Node(534)); This pushes '+', pushes a temporary Node (with 1) created on the stack, and pushes a temporary Node (with 534) created on the stack.

pLNode = &lNode; This assigns the address of the temporary Node created on the stack (with 1) to pLNode, and likewise for pRNode. This is bad.

You could create an object on the stack as you would in Java.
 
  Node('+', new Node(1), new Node(534));


and change the signature of the Node Constructor,
1
2
3
  Node(char o, Node* lNode, Node* rNode)
  {
    // ... 



As it stands, your code is mixing pointers and value semantics. Not good.
I recently converted into the right faith (that being c++) from another language (of far worse reputation than java).

Anyways, a convert's advice: if you want to pass an object by address, it is perfectly legal, but the syntax includes an extra "&" in front of the object's name. So, your code lines 22-29 should look like:
1
2
3
4
5
6
7
  Node(char o, Node& lNode, Node& rNode)
  {
    oper = o;
    pLNode = &lNode;
    pRNode = &rNode;
    leaf = false;
  }


The way you have written your function, when it is called, two new fake objects will be created for each of the arguments of your function. Those two objects will be given some temporary addresses in the memory, which will be recorded in pLNode and pRNode. After the function call is complete (I don't know precisely when), the two fake objects will be destroyed, thus leaving your two pointers pointing at memory that is not reserved by your program.

A natural question comes, why is this the default behavior for the shortest, "common sence" syntax you originally used? The answer I figured for myself is:

Because C++ is a horrible, outmoded, outdated, bloated aberration of a computer language...

...which also happens to be the best one available.


The operator "&" is in some sence the opposite of the operator "*". For example,

1
2
3
4
5
6
7
8
9
10
11
12
13
int a=5;
std::cout <<&a; //will return the physical address of the variable a
int b= *(&a); // b will be assigned the value 5
b=&(*a); 
/*this will crash. It would first attempt to read the memory cell 
of physical address 5 (which is outside the scope 
that the system allows you to read)

If, however, the value of the variable a 
was physical address to which your program 
does have access, the previous line would not crash, 
but make b=a instead.
*/


Please correct me if I am wrong!
Last edited on
Topic archived. No new replies allowed.