Problems overloading the operator<< ( multiple definition)

Pages: 12
I have a parent class and some that derive from it. I want to have a function that will mimic the java's equivalent of .toString()
I searched online and found out that I can overload the << operator which I did, but I'm getting an error:
multiple definition of `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Word&)'

I get the same error for HTMLElement
I'm including two of the files I'm using to test my new findings. Here they are:

HTMLElement.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef HTMLELEMENT_H_
#define HTMLELEMENT_H_

#include <string>
#include <iostream>
using namespace std;

class HTMLElement{
public:
	HTMLElement(string& v, int t);
	virtual int getType();
	virtual string getValue();
protected:
	string value;
	int type;
};

ostream& operator<<(ostream& out, HTMLElement& e){
	out << "(" << e.getType() << " " << e.getValue() << ")";
	return out;
}

#endif 


Word.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef WORD_H_
#define WORD_H_

#include "HTMLElement.h"
#include "URL.h"
#include <string>
using namespace std;


class Word :public HTMLElement {
public:
	Word(string v, URL u);
	string &getURL();
private:
	URL url;
};

ostream& operator<<(ostream& out, Word& w){
	out << "(" << w.getType() << " " << w.getValue() << " " << w.getURL() << ")";
	return out;
}

#endif 


P.S. I tried putting the implementation in the .cpp files and I keep getting the same error.

Any help will be really appreciated!
I think that the error occur since you redeclare the overloaded operator << in your HTMLElement.h and in Word.h.
Yes, you need to put it in the .cpp file (with the definition in the .h)
Note: also I suggest not using
using namespace std;

in your header file.

EDIT:
@firedraco
could you visit this forum for me
http://www.cplusplus.com/forum/general/19345/
Thanks.
Last edited on
@firedraco I did what you suggested and I get an error
expected constructor, destructor, or type conversion before ‘&’ token

I tried without the definition in the .h having the whole
ostream& operator<<
method in my .cpp files and then I get another error
no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char, std::char_traits<char> >&)(& std::cout)), ((const char*)"\012first: ")) << llhe.LinkedList<TYPE>::GetFirst [with TYPE = HTMLElement]()->LLNode<TYPE>::GetValue [with TYPE = HTMLElement]()’
and I get this last same error several times... any idea on how to fix the whole thing?

@olredixsis Just curious, why is it not a good idea to use
using namespace std;
on the .h files?
Make sure you are including the files you need for ostream in the .h file.

h4x0rmx wrote:
Just curious, why is it not a good idea to use
using namespace std;
on the .h files?


It forces others who include you header to have namespace std included, which could cause problems if they having functions named the same or something similar.
I am including the files needed, I still the the same expected constructor error

Is is a good idea to use the namespace in my cpp fles?

Thanks for your help!
Could you post the errors and the .cpp file?

As for namespaces in .cpp files, you can do it and it won't cause any problems. However it is generally a good idea to avoid using using and instead just type out the std::. If it is something large an obnoxious (like my_class::sub_type::info_type::data::static), then it you should try to limit the using only to the scope where it is needed.
Here you go:

HTMLElement.
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
#ifndef HTMLELEMENT_H_
#define HTMLELEMENT_H_
#include <string>
#include <iostream>
/**
 * Interface
 */
class HTMLElement{
protected:
	/**
	 * @note Constructor is protected to make this class abstract,
	 * @note only derived classes can call the constructor
	 */
	HTMLElement(std::string& v, int t);
public:
	virtual int getType();
	virtual std::string getValue();
	const static enum ElementType { TAG = 1, WORD} elementType;
protected:
	std::string value;
	int type;
};

ostream& operator<<(ostream& out, HTMLElement& e);

#endif  


HTMLElement.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "HTMLElement.h"
using namespace std;
HTMLElement::HTMLElement(string& v, int t) : value(v), type(t) {
	return;
}
int HTMLElement::getType() {
	return type;
}
string HTMLElement::getValue() {
	return value;
}

ostream& operator<<(ostream& out, HTMLElement& e){
	out << "(" << e.getType() << " " << e.getValue() << ")";
	return out;
}


Word.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef WORD_H_
#define WORD_H_

#include "HTMLElement.h"
#include "URL.h"
#include <string>
#include <iostream>
class Word :public HTMLElement {
public:
	Word(std::string v, URL u);
	std::string &getURL();
private:
	URL url;
};

ostream& operator<<(ostream& out, Word& w);

#endif 


Word.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "Word.h"
using namespace std;

Word::Word(string v, URL u) : HTMLElement(v, HTMLElement::WORD), url(u) {
	assert(v.length() > 0);
	return;
}
string &Word::getURL(){
	return url.getURL();
}

ostream& operator<<(ostream& out, Word& w){
	out << "(" << w.getType() << " " << w.getValue() << " " << w.getURL() << ")";
	return out;
}
in your header file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ifndef HTMLELEMENT_H_
#define HTMLELEMENT_H_

#include <string>
#include <iostream>
using namespace std;

class HTMLElement{
public:
	HTMLElement(string& v, int t);
	virtual int getType();
	virtual string getValue();
        friend ostream& operator<<(ostream& out, const HTMLElement& e);//<--here
protected:
	string value;
	int type;
};
#endif 
This is what I get:


inc/HTMLElement.h:44: error: ISO C++ forbids declaration of ‘ostream’ with no type
inc/HTMLElement.h:44: error: ‘ostream’ is neither function nor member function; cannot be declared friend
inc/HTMLElement.h:44: error: expected ‘;’ before ‘&’ token
inc/HTMLElement.h:56: error: expected constructor, destructor, or type conversion before ‘&’ token
src/HTMLElement.cpp: In function ‘std::ostream& operator<<(std::ostream&, const HTMLElement&)’:
src/HTMLElement.cpp:28: error: passing ‘const HTMLElement’ as ‘this’ argument of ‘virtual int HTMLElement::getType()’ discards qualifiers
src/HTMLElement.cpp:28: error: passing ‘const HTMLElement’ as ‘this’ argument of ‘virtual std::string HTMLElement::getValue()’ discards qualifiers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ifndef HTMLELEMENT_H_
#define HTMLELEMENT_H_

#include <string>
#include <iostream>
//using namespace std; <--get rid of this

class HTMLElement{
public:
	HTMLElement(std::string& v, int t);//use std::string
        ostream& operator<<(ostream& out,  HTMLElement& e);
	virtual int getType();
	virtual std::string getValue();
        
protected:
	std::string value;
	int type;
};
#endif 
I keep getting the same error.
I'm including my files again, maybe I'm missing something and I can't catch it.

HTMLElement.
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
#ifndef HTMLELEMENT_H_
#define HTMLELEMENT_H_

#include <string>
#include <iostream>

/**
 * Interface
 */
class HTMLElement{
protected:
	/**
	 * Constructor
	 * @note Constructor is protected to make this class abstract,
	 * @note only derived classes can call the constructor
	 */
	HTMLElement(std::string& v, int t);

public:
	virtual int getType();
	virtual std::string getValue();
	const static enum ElementType { TAG = 1, WORD} elementType;
	friend ostream& operator<<(ostream& out, const HTMLElement& e);
protected:
	std::string value;
	int type;
};

ostream& operator<<(ostream& out, const HTMLElement& e);

#endif 


HTMLElement.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "HTMLElement.h"
HTMLElement::HTMLElement(std::string& v, int t) : value(v), type(t) {
	return;
}
int HTMLElement::getType() {
	return type;
}
std::string HTMLElement::getValue() {
	return value;
}
ostream& operator<<(ostream& out, const  HTMLElement& e){
	out << "(" << e.getType() << " " << e.getValue() << ")";
	return out;
}


Word.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef WORD_H_
#define WORD_H_

#include "HTMLElement.h"
#include "URL.h"
#include <string>
#include <iostream>
class Word :public HTMLElement {
public:
	Word(std::string v, URL u);
	std::string &getURL();
	friend ostream& operator<<(ostream& out, const Word& w);
private:
	URL url;
};
ostream& operator<<(ostream& out, const Word& w);
#endif 


Word.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "Word.h"
Word::Word(std::string v, URL u) : HTMLElement(v, HTMLElement::WORD), url(u) {
	assert(v.length() > 0);
	return;
}
std::string &Word::getURL(){
	return url.getURL();
}

ostream& operator<<(ostream& out, const Word& w){
	out << "(" << w.getType() << " " << w.getValue() << " " << w.getURL() << ")";
	return out;
}
where is your code for main.cpp file?
My main main only calls a function:

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
void testHTMLElement(){
	cout << "\n\n==================== test HTMLElement() =======================\n\n";
//	HTMLElement he; // Can't instantiate
//	if(he.getType() == HTMLElement::TAG){
//		cout << "is a TAG" << endl;
//	}else if(he.getType() == HTMLElement::WORD){
//		cout << "is a WORD" << endl;
//	}

	cout << "\n- - - - - - WORD - - - - -\n";
	string str;
	URL * u1;
	str = "http://www.devheads.com/dev/src";
	u1 = new URL(str);
	str = "devheads";
	Word * w1 = new Word(str, *u1);

	cout << "\nw1.getValue:\t" << w1->getValue() << "\nw1.getURL:\t" << w1->getURL() << "\nw1.getType:\t" << w1->getType() << endl;
	assert( w1->getValue() ==  "devheads");
	assert( w1->getURL() ==  "http://www.devheads.com/dev/src");
	assert( w1->getType() == HTMLElement::WORD );


	str = "file:///home/usr/cplusplus.html";
	u1 = new URL(str);
	str = "CPlusPlus";
	Word * w2 = new Word(str, *u1);

	cout << "\nw2.getValue:\t" << w2->getValue() << "\nw2.getURL:\t" << w2->getURL() << "\nw2.getType:\t" << w2->getType() << endl;
	assert( w2->getValue() ==  "CPlusPlus");
	assert( w2->getURL() ==  "file:///home/usr/cplusplus.html");
	assert( w2->getType() == HTMLElement::WORD );
	//	cout << "\ntype: " << w1->getType() << "\nValue: " << w1->getValue() << "\nurl: " << w1->getURL() << endl;


	cout << "\n- - - - - - TAG - - - - -\n";
	string attr;
	string val;
	str = "a";
	attr = "hRef";
	val = "./aAaaa/a.html";
	Tag * t1 = new Tag(str);
	t1->addAttrVal(attr, val);
	attr = "tArget";
	val = "_blank";
	t1->addAttrVal(attr, val);
	attr = "onclick";
	val = "popUpWindow();";
	t1->addAttrVal(attr, val);

	cout << "\nt1.getName:\t" << t1->getName() << "\nt1.LL.size:\t" << t1->attrValLL.GetSize();
	cout << "\nt1.LL.111:\t" << t1->attrValLL.GetFirst()->GetValue().getAttribute() << "=" << t1->attrValLL.GetFirst()->GetValue().getValue() << endl;
	cout << "\nt1.LL.222:\t" << t1->attrValLL.GetFirst()->GetNext()->GetValue().getAttribute() << "=" << t1->attrValLL.GetFirst()->GetNext()->GetValue().getValue() << endl;
	cout << "\nt1.LL.333:\t" << t1->attrValLL.GetLast()->GetValue().getAttribute() << "=" << t1->attrValLL.GetLast()->GetValue().getValue() << endl;

	str = "onClick";
	if( t1->containsAttribute(str) ){
		cout << "\nt1.containsAttribute(" << str << "): YES" << endl;;
		str = "onClick";
		cout << "t1.getAttrValue(" << str << "): " << *t1->getAttrValue(str) << endl;
	}

	LinkedList<HTMLElement> llhe;
	llhe.Insert(*w1, 0);
	llhe.Insert(*w2, 0);
	llhe.Insert(*t1, 0);

	cout << "\n- - - - - - LinkedList<HTMLElement> - - - - -\n";
	cout << "first: " << llhe.GetFirst()->GetValue().getValue() << endl;
	cout << "first: " << llhe.GetFirst()->GetNext()->GetValue().getValue() << endl;
	cout << "first: " << llhe.GetLast()->GetValue().getValue() << endl;

//	cout << "\nfirst: " << llhe.GetFirst()->GetValue() << endl; // <-- I want to be able to do this, it'll help a lot for debugging this and many other (more complex) classes

	delete w1;
	delete w2;
	delete u1;
}
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
#ifndef HTMLELEMENT_H_
#define HTMLELEMENT_H_

#include <string>
#include <ostream>
using std::ostream;
// Forward declare HTMLElement template.
template <typename T> class HTMLElement;
// Prototype for templatized operator<<.
template <typename T>
ostream& operator<<(ostream& ostr, const HTMLElement<T>& e);
/**
 * Interface
 */
template <typename T>
class HTMLElement{
protected:
	/**
	 * Constructor
	 * @note Constructor is protected to make this class abstract,
	 * @note only derived classes can call the constructor
	 */
	HTMLElement(std::string& v, int t);

public:
	virtual int getType();
	virtual std::string getValue();
	const static enum ElementType { TAG = 1, WORD} elementType;
	friend ostream& operator<< <T>(ostream& ostr, const HTMLElement<T>& e);
protected:
	std::string value;
	int type;
};

#endif  


I think I already fixed your problem in overloading operator <<
@olredixsis I'm sorry, but I have to ask... with this new code, how am I supposed to implement an HTMLElement? How about the classes that derive from it? What are you making a template?
How would I instantiate a Word element? Do I have to specify a <T> type?

Thanks again!
wtf? why would you make that a template class?
Oopss sorry for that,

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
#ifndef HTMLELEMENT_H_
#define HTMLELEMENT_H_

#include <string>
#include <ostream>
using std::ostream;
// Forward declare HTMLElement 
class HTMLElement;
// Prototype operator<<.

ostream& operator<<(ostream& ostr, const HTMLElement& e);
/**
 * Interface
 */

class HTMLElement{
protected:
	/**
	 * Constructor
	 * @note Constructor is protected to make this class abstract,
	 * @note only derived classes can call the constructor
	 */
	HTMLElement(std::string& v, int t);

public:
	virtual int getType();
	virtual std::string getValue();
	const static enum ElementType { TAG = 1, WORD} elementType;
	friend ostream& operator<< (ostream& ostr, const HTMLElement& e);
protected:
	std::string value;
	int type;
};

#endif  


I was thinking of a template class when I write that code...
your class is not a template class so just delete the template :)
Last edited on
@olredixsis That works good enough, except for the fact that when I have a instantiate a Word element, the HTMLElement's << operator gets called.
i.e. I have a LinkedList<HTMLElement>, I call
htmlElementLinkedList.GetFirst()->GetValue()
which returns a Word object, and my output is
HTMLElement(1 a)

Do I have to do some casting or should it know what method/function to call?

Thanks!

Edited:
I just noticed that when I have a Word object by itself it knows what << function to call, but not so when my Word is inside a LinkedList<HTMLElement>

Any idea of how I can get the expected output?
Last edited on
Pages: 12