0

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. I, uh... might have double spaced the beginning of each code.

Account.cpp

  #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

  #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

  #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

  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();
     return out;
  }

When I print it out using

cout << "Initialised intNode with " << (intNode) << " ,\n";
cout << "Initialised stringNode with "  << (stringNode) << " ,\n";
cout << "Intiialised accountNode with $" << (accountNode) << "." << endl;

The output is

Initialised intNode with 0x7f9251c03950 ,
Initialised stringNode with 0x7f9251c03970 ,
Intiialised accountNode with $0x7f9251c039c0.

When dereferencing, here is the error

Undefined symbols for architecture x86_64:
  "law_lab07::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, law_lab07::Node<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&)", referenced from:
      _main in main.o
  "law_lab07::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, law_lab07::Node<law_lab07::Account> const&)", referenced from:
      _main in main.o
  "law_lab07::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, law_lab07::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
6
  • Posting the errors will help. But from what I can see you're implementing templates in the cpp file when they should go in the header file.
    – David G
    Commented Oct 20, 2014 at 4:47
  • And while posting the errors, maybe fix your inserter operator; it is missing a return reference. And I think you're going to find this answer to a similar question quite-helpful. (that answer is stellar, btw).
    – WhozCraig
    Commented Oct 20, 2014 at 4:50
  • The declaration of your inserter needs to be a template as well.
    – David G
    Commented Oct 20, 2014 at 4:53
  • @0x499602D2 - The implementation of the template is in a .template file which is #included in the header file.
    – fOrceez
    Commented Oct 20, 2014 at 5:53
  • @WhozCraig - inserter?
    – fOrceez
    Commented Oct 20, 2014 at 5:54

2 Answers 2

1

First, always compile with Warnings. GCC gave me the good hints, and I believe Clang would do so too.

You have a problem with the definition of your operator, as it is a non template friend. Please take a look at http://en.cppreference.com/w/cpp/language/friend

The solution is below :

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() const;
    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& a)
              {
                 return out << a.getData();
              }

 private:
    T data;
    Node<T> *next;
    Node<T> *prev;
 };
 #include "Node.template"
}
#endif

Note that you'll need to make your getData() method a const one to compile.

Also don't forget to dereference your pointer in the main as suggested previously by the others :

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

This is the Account.h file I made :

using namespace std;

namespace myNamespace{
class Account
{
    public:
        Account(){}
        Account(int initialValue);
        void deposit(int amount);
        void withdraw(int amount);
        void setName(std::string newName);
        int balance() const;
        bool has_funds() const;
        std::string getName();
        friend int& operator += (Account& a,const Account& b);
        friend std::ostream& operator << (std::ostream& out, const Account& a);

    protected:
    private:
        int acct_balance;
        string name;
};
}
#endif // ACCOUNT_H

Also add the "return" in the operator<< implementation of Account

7
  • I'm not sure what the problem is, but I get am getting <b>Initialised stringNode with hello, Segmentation fault: 11</b>
    – fOrceez
    Commented Oct 20, 2014 at 7:34
  • Could you try to replace a.getData() with a "test\n" string in the operator<< implementation ? I'm not having any issues with the code I compiled.
    – Lectem
    Commented Oct 20, 2014 at 7:37
  • Just in case I posted the Account.h file I made as you didn't give us one, but I doubt it comes from this.
    – Lectem
    Commented Oct 20, 2014 at 7:43
  • Don't forget to add the return keyword in your Account operator<<
    – Lectem
    Commented Oct 20, 2014 at 7:50
  • Yeah, that's about the same as mine... I'm honestly very puzzled. Thanks for helping, Lactern :)
    – fOrceez
    Commented Oct 20, 2014 at 7:50
0

I believe the problem lies in cout << "Intiialised accountNode with $" << accountNode << "." << endl;. You're trying to print a Node<Account>* instead of a Node<Account>, which you have no overload for.

1
  • Right. Sorry, I should clarify that even when I dereference my pointers, I cannot print them with the overloader :/ I will edit the main post with my error
    – fOrceez
    Commented Oct 20, 2014 at 5:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.