Author Topic: Output operator overloading and templates  (Read 572 times)

0 Members and 1 Guest are viewing this topic.

Offline forceez

  • NULL
  • Posts: 1
  • Cookies: 0
    • View Profile
Output operator overloading and templates
« on: October 19, 2014, 01:48:26 pm »
Cannot get the << overload working and cannot print the 'Account' instance using 'getter' method through Node. Not entirely sure what additional information to provide, please just ask for anything else I didn't clarify!
There is very obviously something wrong with my operator overloading, but I'm not sure what it is.

Account.cpp
Code: [Select]
#include "Account.h"
namespace myNamespace{
   // CONSTRUCTOR
   Account::Account(int initialValue)
   {
       acct_balance = initialValue;
   }
   //MUTATOR MEMBER FUNCTION
   void Account::deposit(int amount)
   {
       acct_balance += amount;
   }


   void Account::withdraw(int amount)
   {
       acct_balance -= amount;
   }


   void Account::setName(std::string newName)
   {
      name = newName;
   }
   //QUERY MEMBER FUNCTION
   int Account::balance() const
   {
       return acct_balance;
   }


   bool Account::has_funds() const
   {
      return (acct_balance > 0.0);
   }


   std::string Account::getName()
   {
      return name;
   }


   int& operator += (Account& a,const Account& b)
   {
      a.acct_balance += b.balance();
      return a.acct_balance;
   }


   std::ostream& operator << (std::ostream& out, const Account& a)
   {
      out << a.acct_balance;
   }
};



main.cpp
Code: [Select]

#include <iostream>
#include <string>
#include "Account.h"
#include "Node.h"




using namespace myNamespace;
using namespace std;


int main()
{
   Node<int>* intNode = new Node<int>(5);
   Node<std::string>* stringNode = new Node<std::string>("hello");
   Account* acc1 = new Account();
   Node<Account>* accountNode = new Node<Account>(*acc1);
   


   cout << "Initialised intNode with " << (intNode)->getData() << " ,\n";
   cout << "Initialised stringNode with "    << stringNode->getData() << " ,\n";
   cout << "Intiialised accountNode with $" << accountNode << "." << endl;
   return 0;
}


/*
Modify the Node class you produced in the last few weeks so that it becomes
a class template for a Node that can store a pointer to a generic type
instance. The constructor for your new Node returns a pointer to the newlycreated
Node instance, which has been created in the heap. Instantiate a
Node to store a pointer to an int; a pointer to a string; and a pointer to
an Account.
*/


Node.h
Code: [Select]

#ifndef NODE_H
#define NODE_H
#include <iostream>
using namespace std;


namespace myNamespace{
{
   template <class T>
   class Node
   {
   public:
      Node(T const& initData, Node<T>* const& initPrev = NULL, Node<T>* const& initNext = NULL);
      void setData(T newData);
      T getData();
      void setPrev(Node<T>* newPrev);
      Node<T>* getPrev();
      void setNext(Node<T>* newNext);
      Node<T>* getNext();


      friend std::ostream& operator << (std::ostream& out, const Node<T>& a);
   private:
      T data;
      Node<T> *next;
      Node<T> *prev;
   };
   #include "Node.template"
}
#endif


Node.template
Code: [Select]

template <class T>
Node<T>::Node(T const& initData, Node<T>* const& initPrev, Node<T>* const& initNext)
{
   data = initData;
   prev = initPrev;
   next = initNext;
}


template <class T>
void Node<T>::setData(T newData)
{
   data = newData;
}


template <class T>
T Node<T>::getData()
{
   return data;
}


template <class T>
void Node<T>::setPrev(Node<T>* newPrev)
{
   prev = newPrev;
}


template <class T>
Node<T>* Node<T>::getPrev()
{
   return prev;
}


template <class T>
void Node<T>::setNext(Node<T>* newNext)
{
   next = newNext;
}


template <class T>
Node<T>* Node<T>::getNext()
{
   return next;
}


template <class T>
std::ostream& operator << (std::ostream& out, const Node<T>& a)
{
   out << a->getData();
}



When I print it out using


Code: [Select]
cout << "Initialised intNode with " << (intNode) << " ,\n";
cout << "Initialised stringNode with "    << (stringNode) << " ,\n";
cout << "Intiialised accountNode with $" << (accountNode) << "." << endl;


The output is
Code: [Select]
Initialised intNode with 0x7f9251c03950 ,
Initialised stringNode with 0x7f9251c03970 ,
Intiialised accountNode with $0x7f9251c039c0.


When dereferencing, here is the error



Code: [Select]
Undefined symbols for architecture x86_64:
  "myNamespace::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, myNamespace::Node<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&)", referenced from:
      _main in main.o
  "myNamespace::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, myNamespace::Node<myNamespace::Account> const&)", referenced from:
      _main in main.o
  "myNamespace::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, myNamespace::Node<int> const&)", referenced from:
      _main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [runfile] Error 1

EDIT: IT'S SOLVED, EVERYBODY! Turns out the error was because I'm stupid! xP
« Last Edit: October 20, 2014, 10:09:14 am by forceez »

Offline ArkPhaze

  • Peasant
  • *
  • Posts: 136
  • Cookies: 20
  • null terminated
    • View Profile
Re: Output operator overloading and templates
« Reply #1 on: November 03, 2014, 07:47:14 am »
Code: [Select]
std::ostream& operator << (std::ostream& out, const Account& a)
   {
      out << a.acct_balance;
   }

HINT: The return of the << operator to me says a reference to std::ostream here, yet I don't see a return keyword in this function.

That's just for starters, it looks like you don't have things properly set up here. What does the header file look like? And why is the namespace in with the definition of all of the class functionality? I don't see the contents of the Account header file in your post.

And the reason why dereferencing brings up these errors is because the << operator is already overloaded by default for pointer types. This will therefore, compile without you having to overload the << operator at all manually:
Code: [Select]
#include <iostream>

class myobj
{

};

int main()
{
  myobj *pobj = new myobj;
  std::cout << pobj << std::endl;
  delete pobj;
}
« Last Edit: November 03, 2014, 07:52:15 am by ArkPhaze »
sig=: ArkPhaze

[ J/ASM/.NET/C/C++ - Software Engineer ]

Offline s3my0n

  • Knight
  • **
  • Posts: 276
  • Cookies: 58
    • View Profile
    • ::1
Re: Output operator overloading and templates
« Reply #2 on: November 04, 2014, 02:20:24 pm »
HINT: use [ code=c++ ] when pasting code. (Without spaces of course).
« Last Edit: November 04, 2014, 02:21:08 pm by s3my0n »
Easter egg in all *nix systems: E(){ E|E& };E