Why this header file does not work for my .cpp?

Nov 1, 2019 at 10:31pm
The .cpp file below compiles successfully if I do not include the header file btree.h. However I would like to put header file separately. Can someone review the header file and see what I am missing? If I use the header file, it gives me several errors during compilation (examples of errors):
1>------ Build started: Project: Project17, Configuration: Debug Win32 ------
1>btree.cpp
1>C:source\repos\Project17\btree.h(6,12): error C3646: 'val': unknown override specifier
1>C:\source\repos\Project17\btree.h(6,12): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>C:\source\repos\Project17\btree.h(9,17): error C2061: syntax error: identifier 'string'
1>C:\source\repos\Project17\btree.h(18,21): error C2061: syntax error: identifier 'string'
1>C:\source\repos\Project17\btree.h(23,44): error C2061: syntax error: identifier '


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
//btree.h file. I would like to use a separate header file
#include <string>

class Bnode
{
public:
	string val;
	Bnode* pLeft;
	Bnode* pRight;
	Bnode(string s);
};

class Btree
{
public:
	Btree();
	
	void print();
	void insert(string s);

private:
	Bnode* root;
	void print_subtree(Bnode* p);
	Bnode* insert_at_subtree(Bnode* p, string s);
};

//******* THE BELOW IS THE .CPP FILE. NOTE .CPP is functional at this time
//******* without the header file. But I would like to use the header file 


#include "btree.h"
#include <iostream>
#include <string>

using namespace std;

class Bnode
{
public:
	string val;
	Bnode* pLeft;
	Bnode* pRight;
	Bnode(string s) { val = s; pLeft = pRight = nullptr; }

};

class Btree
{
public:
	Btree()
	{
		root = nullptr;
	}

	void print()
	{
		print_subtree(root);
	}

	void insert(string s)
	{
		root = insert_at_subtree(root, s);
	}

private:
	Bnode* root;
	void print_subtree(Bnode* p);
	Bnode* insert_at_subtree(Bnode* p, string s);
};

void Btree::print_subtree(Bnode* p)
{
	if (!p)
	{
		return;
	}
	print_subtree(p->pLeft);
	cout << p->val << endl;
	print_subtree(p->pRight);

}

Bnode* Btree::insert_at_subtree(Bnode* p, string s)
{
	if (!p)
	{
		return new Bnode(s);
	}

	if (s < p->val)
	{
		p->pLeft = insert_at_subtree(p->pLeft, s);
	}
	else if (s > p->val)
	{
		p->pRight = insert_at_subtree(p->pRight, s);


	}
	return p;
}


int main()
{
	Btree my_tree;
	string s;
	while (true)
	{
		cout << "Enter a name: ";
		getline(cin, s);
		if (s == "")
		{
			break;
		}
		my_tree.insert(s);
	}
	my_tree.print();
	cout << endl;
	return 0;
}
Last edited on Nov 1, 2019 at 10:35pm
Nov 1, 2019 at 10:49pm
I am assuming that your project consists of btree.h, and btree.cpp.
If so, first thing is to remove the definition of the Bnode class from the .cpp file. It's already defined in the .h file.

In your .cpp is where you can define the functions themselves, for example
Bnode::Bnode(string s) { val = s; pLeft = pRight = nullptr; }

Likewise, don't redefine Btree. But you do need to define the functions, e.g. your constructor, print() and insert(string).

Also, always use header guards
A header guard will look something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// my_header.h
#ifndef MY_HEADER_GUARD_HPP
#define MY_HEADER_GUARD_HPP

class A {

};

class B {

};

void whatever_else();

#endif 
Last edited on Nov 1, 2019 at 10:51pm
Nov 1, 2019 at 11:21pm
1
2
3
4
5
6
7
8
9
10
#include <string>

class Bnode
{
public:
	string val; // error: 'string' does not name a type
	Bnode* pLeft;
	Bnode* pRight;
	Bnode(string s); // error
};

You have not told the compiler, what string is.

You have included a Standard Library header 'string' that does define some types, even a 'string', but not in the global scope. Those definitions are within namespace 'std' and you should state that explicitly:
1
2
3
4
5
6
7
8
9
10
#include <string>

class Bnode
{
public:
	std::string val; // ok
	Bnode* pLeft;
	Bnode* pRight;
	Bnode(std::string s); // ok
};



Note on constructor.
There is member initializer list syntax that is occasionally compulsory and sometimes more efficient.
1
2
3
Bnode::Bnode( const string & s ) // by reference could be cheaper than by value
 : val(s), pLeft{nullptr}, pRight{nullptr} // member initializer list
{}

However, since C++11 in-class initializers have been possible:
1
2
3
4
5
6
7
8
9
10
11
12
class Bnode
{
public:
	std::string val;
	Bnode* pLeft  {nullptr};
	Bnode* pRight {nullptr};
	Bnode( const std::string& );
};

Bnode::Bnode( const string & s )
 : val(s)
{}

Nov 2, 2019 at 7:43am
Thank you folks. It helpded.
Topic archived. No new replies allowed.