simple OOP Linker error help

Started by
14 comments, last by sheep19 15 years, 11 months ago
Hello. It's been a while since I even coded because school exams are approaching, so I decided to make a quick revision today. I grabbed my book and wrote a simple program. I decided to break the code in files myself. So, I have done it, but I'm missing something because I get a nasty liker error (my worst). So here's my code: Classes.h

#ifndef CLASSES_H
#define CLASSES_H

class Critter
{
public:
	Critter( const std::string& name = "" );
	std::string GetName() const;

private:
	std::string m_Name;
};

class Farm
{
public:
	Farm( int spaces = 1 );
	void Add( const Critter& aCritter );
	void RollCall() const;

private:
	std::vector< Critter > m_Critters;
};

#endif




main

#include <iostream>
#include <string>
#include <vector>

#include "Classes.h"

int main()
{
	Critter crit( "Poochie" );
	std::cout << "My critter's name is " << crit.GetName() << std::endl;

	std::cout << "\nCreating critter farm.\n";
	Farm myFarm(3);

	std::cout << "\nAdding three critters to the farm.\n";
	myFarm.Add( Critter("Moe") );
	myFarm.Add( Critter("Larry") );
	myFarm.Add( Critter("Curly") );

	std::cout << "\nCalling Roll...\n";
	myFarm.RollCall();

	system("PAUSE");
	return 0;
}




Classes.cpp

#include <iostream>
#include <string>
#include <vector>

#include "Classes.h"

Critter::Critter( const std::string& name ): m_Name( name )
{
}

inline std::string Critter::GetName() const
{
	return m_Name;
}

Farm::Farm( int spaces )
{
	m_Critters.reserve( spaces );
}

void Farm::RollCall() const
{
	for( std::vector< Critter >::const_iterator iter = m_Critters.begin(); iter < m_Critters.end(); ++iter )
		std::cout << iter->GetName() << " here.\n";
}

Edit: Oops, forgot the error. 1>Linking... 1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall Farm::Add(class Critter const &)" (?Add@Farm@@QAEXABVCritter@@@Z) referenced in function _main 1>C:\My Documents\Visual Studio 2005\Projects\Test2\Debug\Test2.exe : fatal error LNK1120: 1 unresolved externals [Edited by - sheep19 on May 8, 2008 8:36:20 AM]
Advertisement
What's the linker error?
Shouldn't there be a classes.cpp file with the actual implememtation of the class methods?
Quote:Original post by gah_ribaldi
Shouldn't there be a classes.cpp file with the actual implememtation of the class methods?


Yes, there is, but I haven't included it. Maybe I should.
Um, where's your Add( ... ) function for farm?

You declare it in classes.h, but in your classes.cpp there is no implementation. So of course, when you try to invoke that function in main, your link will fail.

Just looks like you forgot to write the actual function :)
Well, that should be pretty straight forward. Just what the linker complains about: You didn't provide an implementation of the Farm::Add() method.

This is what's missing from your Classes.cpp file:
void Farm::Add(const Critter& aCritter) {  m_Critters.push_back(aCritter);}


EDIT: Darn, beaten to it. Need... to... type... faster!

-Markus-
Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
What a silly mistake! :(

Thanks for the help!
I decided to split the classes in different files. I achieved this in two ways, but I'm not sure which one is the best.

1ST WAY:

Critter.h
#ifndef CRITTER_H#define CRITTER_H<b>class Farm;</b>class Critter{public:	Critter( const std::string& name = "" );	std::string GetName() const;private:	std::string m_Name;};#endif


Farm.h
#ifndef FARM_H#define FARM_H    //#include "Critter.h" -> not using thisclass Critter;class Farm{public:	Farm( int spaces = 1 );	void Add( const Critter& aCritter );	void RollCall() const;private:	std::vector< Critter > m_Critters;};#endif


Farm.cpp
#include <iostream>#include <string>#include <vector>#include "Farm.h"#include "Critter.h" // ->have to use thisFarm::Farm( int spaces ){	m_Critters.reserve( spaces );}void Farm::Add( const Critter& aCritter ){	m_Critters.push_back( aCritter );}void Farm::RollCall() const{	for( std::vector< Critter >::const_iterator iter = m_Critters.begin(); iter < m_Critters.end(); ++iter )		std::cout << iter->GetName() << " here.\n";}


So I'm avoiding cyclic dependency. I think it's unnecessary though because Critter doesn't need Farm.

--------------------------------------------------------------------------------

2nd way

Critter.h
#ifndef CRITTER_H#define CRITTER_Hclass Critter{public:	Critter( const std::string& name = "" );	std::string GetName() const;private:	std::string m_Name;};#endif


Farm.h"
#ifndef FARM_H#define FARM_H#include "Critter.h"class Farm{public:	Farm( int spaces = 1 );	void Add( const Critter& aCritter );	void RollCall() const;private:	std::vector< Critter > m_Critters;};#endif


Farm.cpp
#include <iostream>#include <string>#include <vector>#include "Farm.h"Farm::Farm( int spaces ){	m_Critters.reserve( spaces );}void Farm::Add( const Critter& aCritter ){	m_Critters.push_back( aCritter );}void Farm::RollCall() const{	for( std::vector< Critter >::const_iterator iter = m_Critters.begin(); iter < m_Critters.end(); ++iter )		std::cout << iter->GetName() << " here.\n";}

--------------------------------------------------------------------------------
So that's it. I think that the first way is better, but I want to be sure. Thanks in advance.
I think you want the first way, but you want to take out the unnecessary "class Farm;" from critter.h.

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

Quote:Original post by superpig
I think you want the first way, but you want to take out the unnecessary "class Farm;" from critter.h.


It's unnecessary only in this case, isn't it? If Critter used Farm in a way I would it need that?

This topic is closed to new replies.

Advertisement