Main.cpp

This is where the problem lies.

#include <iostream>
#include <time.h>
#include <math.h>
#include <iomanip>
#include "LinkedList.h"
#include <fstream>
#include <string>

using namespace std;

void main(void)
{
	LinkedList Customers;
	Customer* newCustomer;
	Entry* test;
        int i = 0;

	newCustomer = new Customer(1001, "Olly", "07/10/1988", "17 Bob Lane", "Hobbs Road", "UB3 RKL", "01234567891");
	Customers.add(*newCustomer);

	test = Customers.returnObject(2);
	[B]i = test->info->returnCustomerID();[/B]
	cout << i;
	system("pause");
}

LinkedList.h

class Object
{
public:
	Object(){;}
	virtual ~Object(){;}
	virtual ostream& printOn(ostream&) const = 0;
	int returnCustomerID();
	friend ostream& operator << (ostream& out, const Object& theObj)
	{
			theObj.printOn(out);
			return out;
	}
};

class Entry
{
public:
	Entry* next;
	Object* info;
	Entry(Object* obj)
	{
		info = obj;
		next = NULL;
	}
	~Entry(){delete info;}
};

class LinkedList
{
	Entry* start_ptr;
	int NoEntries;
public:
	LinkedList();
	~LinkedList();
	Entry* returnStartPtr() const{return start_ptr;}
	void add(Object& obj);
	Entry* returnObject(int position);
	ostream& print(ostream& co);
};

class Customer:public Object
{
	int customerID;

public:
	Customer(int customerID, string name, char dateOfBirth[], string address1, string address2, string postcode, string contactNumber)
	{
	this->customerID = customerID;
	this->name = name;
	strcpy(this->dateOfBirth, dateOfBirth);
	this->address1 = address1;
	this->address2 = address2;
	this->postcode = postcode;
	this->contactNumber = contactNumber;
	}

	int returnCustomerID()
	{
		return customerID;
	}

	ostream& printOn(ostream& co) const
	{ 
		co << "--------------------------" << endl;
		co << "Customer ID: " << customerID << endl;
		co << "Name: " << name << endl;
		co << "Date of Birth: " << dateOfBirth << endl;
		return co;
	}

LinkedList.cpp

#include <iostream>
#include <stdlib.h>
#include <string>
#include "LinkedList.h" 

using namespace std;

LinkedList::LinkedList()
{
	start_ptr = NULL; 
	NoEntries = 0;
}

LinkedList::~LinkedList()
{
}

void LinkedList::add(Object& newEntry)
{
	if(start_ptr == NULL)
	{
		Entry* newElement  = new Entry(&newEntry); 
		start_ptr = newElement;
	} else {
		Entry* tempObj = start_ptr;
		while(tempObj->next != NULL)
			tempObj = tempObj->next;
		Entry* newElement  = new Entry(&newEntry); 
		tempObj->next = newElement;			                 
	}
	NoEntries++;
}

Entry* LinkedList::returnObject(int position)
{
	int count;
	Entry *objectToReturn = start_ptr;
	for(count = 0; count < position; count++)
		objectToReturn = objectToReturn->next;
	return objectToReturn;
}

- Ok here goes.
- Main.cpp is where the program is run. First of all I create a linkedlist of customers. This goes through Entry->Object->Customers. Don't ask why I have done it this way. I have to.
- I want to access variables inside Customer, outside, in Main.cpp.
- I have tried doing it as above, but the bolded line isn't liked. The program compiles but returns runtime error.
- Error 19 error LNK2019: unresolved external symbol "public: int __thiscall Object::returnCustomerID(void)" (?returnCustomerID@Object@@QAEHXZ) referenced in function _main main.obj bankusingarrays
- Ignore the name bankusingarrays - that was previous project, I know I am not using arrays lol.

I'm not really sure what to do now. As the program stands. I add 4 customers (I have only shown 1, named Olly, here but in actual program there are 4).

I want to enter the position in the linked list and return the object, to main, to then test the customerID against variable x. Obviously to do so I need to get the customerID from each object to then compare. This is what I am trying to do at the moment, get the ID of the Customer object in position 2, in linked list of Customers.

Ok. Well.... yes sorry its a long one, I couldn't think of how else to explain it!

i = test->info->returnCustomerID();

Did you ever declare 'i' ?

lol yes I am not that silly. My codes a lot bigger than that, I just didn't want to waste too much space.

int i = 0; <---- inside void main(void)

>unresolved external symbol "public: int __thiscall Object::returnCustomerID(void)"
returnCustomerID is declared in Object (why?), not defined, and it's not virtual. I'm not surprised your linker is complaining that it can't find the definition.

>unresolved external symbol "public: int __thiscall Object::returnCustomerID(void)"
returnCustomerID is declared in Object (why?), not defined, and it's not virtual. I'm not surprised your linker is complaining that it can't find the definition.

Virtual doesn't do anything. (gives the same error but with virtual infront of the function error)

Because Customers are a type of Object.

And not sure about define, don't understand?

>And not sure about define, don't understand?
Functions need a body. No body, and the linker bitches at you. Example:

void foo();

int main()
{
  foo(); // Linker error, foo has no body
}

n'est-ce pas?

>And not sure about define, don't understand?
Functions need a body. No body, and the linker bitches at you. Example:

void foo();

int main()
{
  foo(); // Linker error, foo has no body
}

n'est-ce pas?

Ok I get that but I have returnCustomerID in Customer class. Is that not enough? I thought it would pick it up

i.e. I declare it in Object, write the body in Customer, and it would link the 2 together as Customers are Objects (as declared in main.cpp)

By all means if I declare the body in object i.e. return CustomerID, inside Object it won't like it because there is no CustomerID, because thats in Customer, not Object.

>i.e. I declare it in Object, write the body in Customer, and it would link
>the 2 together as Customers are Objects (as declared in main.cpp)
To translate: You're looking for the behavior of a pure virtual member function without declaring the member function as pure virtual. How silly.

Here's the magic incantation to make your dreams reality:

virtual int returnCustomerID() = 0;

>i.e. I declare it in Object, write the body in Customer, and it would link
>the 2 together as Customers are Objects (as declared in main.cpp)
To translate: You're looking for the behavior of a pure virtual member function without declaring the member function as pure virtual. How silly.

Here's the magic incantation to make your dreams reality:

virtual int returnCustomerID() = 0;

lol thanks. So does making it = 0 make it pure virtual?

That gets past that error but creats more errors in the rest of my program. I have more than 1 type of Object, one is Accounts which is abstract, I have types of Account e.g.

lass CurrentAccount:virtual public Account
{
private:
	
public:
	CurrentAccount(int customerID, int accountID, int balance):Account(customerID, accountID, balance, savingsRate, borrowRate, overdraftLimit, "Current Account")
	{
		savingsRate = 1;
		borrowRate = 12;
		overdraftLimit = 500;
	}
};

(Account is the same as Customer but with different variables, also is public Object).

Its not liking this as my Current Account is abstract.

Error 8 error C2259: 'CurrentAccount' : cannot instantiate abstract class d:\c++\bankusingarrays\main.cpp 130 bankusingarrays

This is when I try to create a newAccount (exactly the same as above with newCustomer)

i.e.

newAccount = new CurrentAccount(1002, 100002, 35);

So basically it doesn't like me creating new types of Account.

>So does making it = 0 make it pure virtual?
Sadly, yes. It's terribly obscure and clever on the part of C++'s designers (much like destructors being the constructor name with a leading tilde), which is a shame.

>So basically it doesn't like me creating new types of Account.
Classes that derive from Account must override the pure virtual member functions in the derived class. If you don't, the derived class inherits the abstract status. You say Account is abstract, so it should have at least one such member function, yet your CurrentAccount class only defines a constructor.

Comments
Uber helpful.

Sadly, yes. It's terribly obscure and clever on the part of C++'s designers (much like destructors being the constructor name with a leading tilde), which is a shame.

Luckily I remember about the stupid squiggle (~~~~ EEK!!!!!!!)

Classes that derive from Account must override the pure virtual member functions in the derived class. If you don't, the derived class inherits the abstract status. You say Account is abstract, so it should have at least one such member function, yet your CurrentAccount class only defines a constructor.

Not sure I understand what member function is? I have Account class with a constructor (if that what you mean?) and also so you're saying my CurrentAccount etc. are being abstract now?

class Account:public Object
{
protected:
	int customerID;
	int accountID;
	int balance;
	int savingsRate;
	int borrowRate;
	int overdraftLimit;
	string accountType;

public:
	Account(int customerID, int accountID, int balance, int savingsRate, int borrowRate, int overdraftLimit, string accountType)
	{
	this->customerID = customerID;
	this->accountID = accountID;
	this->balance = balance;
	this->savingsRate = savingsRate;
	this->borrowRate = borrowRate;
	this->overdraftLimit = overdraftLimit;
	this->accountType = accountType;
	}
};

Thanks for your help... I am pretty new to this and my lecturers are crap. I asked how I could get access to variables because I technically can't in main.cpp etc. and he said 'Yes that is completely right. What you have to do is create some functions that allow that, so it links up Customers with Objects', he then walked off, which wasn't much help as I knew that. Douche.

>Not sure I understand what member function is?
Member functions are the politically correct term, but you may be learning them as methods. I imagine your Account class looks something like this:

class Account: public Object {
public:
  Account() { /* ... */ }
  void someAccountSpecificFunction() = 0;
};

Or, since you've now made the Object class abstract by making returnCustomerID pure (one or more pure member functions makes a class abstract, by the way), you need to override it in Account if you want to create Account objects:

class Account: public Object {
public:
  Account() { /* ... */ }
  
  virtual int returnCustomerID()
  {
    // ...
  }
};

Defining the inherited pure member functions will make the class concrete.

Ok understand about methods and functions. Was the 'member' bit I didn't understand.

Ok so basically, if I get you straight.

Any classes with are pure inheritence, anything which is sibbling (trying to think of simple terms here) of this must have the functions of the abstract class above it? (i means the one that makes it pure), even if they aren't used by that?

Abstractness is inherited if you don't override a pure virtual method, and you can't create objects of an abstract class:

class A {
public:
  virtual void foo() = 0;
};

class B: public A {
  // Inherits the pure A::foo()
};

class C: public B {
  // Inherits the pure B::foo()
};

int main()
{
  A a; // Error! A is abstract
  B b; // Error! B is also abstract
  C c; // Error! C is abstract too
}

As soon as you override all of the pure virtual methods, the abstractness goes away from that point on and you can create objects of that class:

class A {
public:
  virtual void foo() = 0;
};

class B: public A {
public:
  // Overrides A::foo()
  virtual void foo() {}
};

class C: public B {
  // Inherits B::foo()'s override
};

int main()
{
  A a; // Error! A is abstract
  B b; // OK
  C c; // OK
}

Funnily enough, that makes perfect sense!!!!!

THANKS LOADS!!!! :)

This article has been dead for over six months. Start a new discussion instead.