Include / Linking Problems with g++

I'm trying to understand how to break up a program into main, header, and implementation files. I'm using a stack program that runs without error when it is compiled all in the same file. All files are located in the same folder on my desktop. I've broken the program up into a main file, a header file, and an implementation file. Here is the code:

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
//main function - stack.cpp

#include "stack.h"

int main()
{
	stacktype stack; 
	string newelement, poppedelement;
	char quest;
	
	createstack(stack);

	cout << "Do you want to enter data (y/n)? ";
	cin >> quest;
	while((quest == 'y' || quest == 'Y') && !(fullstack(stack)))
	{
		cout << "Please enter name: ";
		cin >> newelement;
		
		push(stack, newelement);
		
		cout << "Do you want to enter data (y/n)? ";
		cin >> quest;
	}
	
	cout << endl << endl;
	
	while(!emptystack(stack))
	{
		pop(stack, poppedelement);
		cout << poppedelement << endl;
	}
		
	destroystack(stack);

}


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
//header function - stack.h

#ifndef _STACK_H
#define _STACK_H

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

const int maxstack = 5;

struct stacktype
{
	string name[maxstack];
	int top;
};

void createstack(stacktype &stack);
void destroystack(stacktype &stack);
bool fullstack(stacktype stack);
void push(stacktype &stack, string &newelement);
bool emptystack(stacktype stack);
void pop(stacktype &stack, string &poppedelement);

#endif 


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
//implementation file - imp.cpp

void createstack(stacktype &stack)
{
	stack.top = -1;
}

void destroystack(stacktype &stack)
{
	stack.top = -1;
}

bool fullstack(stacktype stack)
{
	if(stack.top == maxstack -1) return 1;
	else return 0;
}

void push(stacktype &stack, string &newelement)
{
	stack.top++;
	stack.name[stack.top] = newelement;

}

bool emptystack(stacktype stack)
{
	if(stack.top == -1) return 1;
	else return 0;
}

void pop(stacktype &stack, string &poppedelement)
{
	poppedelement = stack.name[stack.top];
	stack.top--;
}



C:\Users\Loot\Desktop\Program Dump>g++ -o stack stack.cpp
C:\Users\Loot\AppData\Local\Temp\ccZifXj8.o:stack.cpp:(.text+0x99): undefined re
ference to `createstack(stacktype&)'
C:\Users\Loot\AppData\Local\Temp\ccZifXj8.o:stack.cpp:(.text+0x113): undefined r
eference to `push(stacktype&, std::string&)'
C:\Users\Loot\AppData\Local\Temp\ccZifXj8.o:stack.cpp:(.text+0x18f): undefined r
eference to `fullstack(stacktype)'
C:\Users\Loot\AppData\Local\Temp\ccZifXj8.o:stack.cpp:(.text+0x24e): undefined r
eference to `pop(stacktype&, std::string&)'
C:\Users\Loot\AppData\Local\Temp\ccZifXj8.o:stack.cpp:(.text+0x2ae): undefined r
eference to `emptystack(stacktype)'
C:\Users\Loot\AppData\Local\Temp\ccZifXj8.o:stack.cpp:(.text+0x347): undefined r
eference to `destroystack(stacktype&)'
collect2: ld returned 1 exit status

C:\Users\Loot\Desktop\Program Dump>


The error messages seem like the program doesn't recognize the implementation file. I've tried #include 'ing it, to the tune of many errors. Any help figuring this out would be monstrously appreciated.
When you are building sources in one go using gcc, you need to include all source files you will link together.

$ g++ -o stack stack.cpp imp.cpp


Alternatively, you can split the compile and link commands

$ g++ -c stack.cpp
$ g++ -c imp.cpp
$ g++ -o stack stack.o imp.o
Thanks for the reply, that's an extremely useful puzzle piece that I was missing.

However, when I enter $ g++ -o stack stack.cpp imp.cpp at the command line I get an entirely different set of compile errors this time around:


C:\Users\Loot\Desktop\Program Dump>g++ -o stack stack.cpp imp.cpp
imp.cpp:3: error: variable or field 'createstack' declared void
imp.cpp:3: error: 'stacktype' was not declared in this scope
imp.cpp:3: error: 'stack' was not declared in this scope
imp.cpp:8: error: variable or field 'destroystack' declared void
imp.cpp:8: error: 'stacktype' was not declared in this scope
imp.cpp:8: error: 'stack' was not declared in this scope
imp.cpp:13: error: 'stacktype' was not declared in this scope
imp.cpp:14: error: expected ',' or ';' before '{' token
imp.cpp:19: error: variable or field 'push' declared void
imp.cpp:19: error: 'stacktype' was not declared in this scope
imp.cpp:19: error: 'stack' was not declared in this scope
imp.cpp:19: error: 'string' was not declared in this scope
imp.cpp:19: error: 'newelement' was not declared in this scope
imp.cpp:26: error: 'stacktype' was not declared in this scope
imp.cpp:27: error: expected ',' or ';' before '{' token
imp.cpp:32: error: variable or field 'pop' declared void
imp.cpp:32: error: 'stacktype' was not declared in this scope
imp.cpp:32: error: 'stack' was not declared in this scope
imp.cpp:32: error: 'string' was not declared in this scope
imp.cpp:32: error: 'poppedelement' was not declared in this scope

C:\Users\Loot\Desktop\Program Dump>


Looks like I'm having scope problems now. I included the header file in the source file, so shouldn't the imp.cpp file have access to those declarations?
Last edited on
I included the header file in the source file, so shouldn't the imp.cpp file have access to those declarations?


Did you include the header file in the "source" file imp.cpp?
I've tried both including and not including the header file in imp.cpp. When I do include it, I get many more error messages.

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Users\Loot>cd desktop

C:\Users\Loot\Desktop>cd program dump

C:\Users\Loot\Desktop\Program Dump>g++ -o stack stack.cpp imp.cpp
In file included from stack.cpp:3:
stack.h:12: error: variable or field 'createstack' declared void
stack.h:12: error: 'stacktype' was not declared in this scope
stack.h:12: error: 'stack' was not declared in this scope
stack.h:13: error: variable or field 'destroystack' declared void
stack.h:13: error: 'stacktype' was not declared in this scope
stack.h:13: error: 'stack' was not declared in this scope
stack.h:14: error: 'stacktype' was not declared in this scope
stack.h:15: error: variable or field 'push' declared void
stack.h:15: error: 'stacktype' was not declared in this scope
stack.h:15: error: 'stack' was not declared in this scope
stack.h:15: error: expected primary-expression before '&' token
stack.h:15: error: 'newelement' was not declared in this scope
stack.h:16: error: 'stacktype' was not declared in this scope
stack.h:17: error: variable or field 'pop' declared void
stack.h:17: error: 'stacktype' was not declared in this scope
stack.h:17: error: 'stack' was not declared in this scope
stack.h:17: error: expected primary-expression before '&' token
stack.h:17: error: 'poppedelement' was not declared in this scope
stack.cpp: In function 'int main()':
stack.cpp:11: error: 'createstack' was not declared in this scope
stack.cpp:15: error: 'fullstack' cannot be used as a function
stack.cpp:20: error: 'push' was not declared in this scope
stack.cpp:28: error: 'emptystack' cannot be used as a function
stack.cpp:30: error: 'pop' was not declared in this scope
stack.cpp:34: error: 'destroystack' was not declared in this scope
In file included from imp.cpp:3:
stack.h:12: error: variable or field 'createstack' declared void
stack.h:12: error: 'stacktype' was not declared in this scope
stack.h:12: error: 'stack' was not declared in this scope
stack.h:13: error: variable or field 'destroystack' declared void
stack.h:13: error: 'stacktype' was not declared in this scope
stack.h:13: error: 'stack' was not declared in this scope
stack.h:14: error: 'stacktype' was not declared in this scope
stack.h:15: error: variable or field 'push' declared void
stack.h:15: error: 'stacktype' was not declared in this scope
stack.h:15: error: 'stack' was not declared in this scope
stack.h:15: error: expected primary-expression before '&' token
stack.h:15: error: 'newelement' was not declared in this scope
stack.h:16: error: 'stacktype' was not declared in this scope
stack.h:17: error: variable or field 'pop' declared void
stack.h:17: error: 'stacktype' was not declared in this scope
stack.h:17: error: 'stack' was not declared in this scope
stack.h:17: error: expected primary-expression before '&' token
stack.h:17: error: 'poppedelement' was not declared in this scope
imp.cpp: In function 'bool fullstack(stacktype)':
imp.cpp:15: error: 'bool fullstack(stacktype)' redeclared as different kind of s
ymbol
stack.h:14: error: previous declaration of 'bool fullstack'
imp.cpp: In function 'bool emptystack(stacktype)':
imp.cpp:28: error: 'bool emptystack(stacktype)' redeclared as different kind of
symbol
stack.h:16: error: previous declaration of 'bool emptystack'

C:\Users\Loot\Desktop\Program Dump>
I would avoid naming something the same as a STL object. It might not be a problem here, but avoid doing anyway.

In the header file, you have a stack struct with functions outside of it. In C++ a struct is almost the same thing as a class,the only difference being strucr members are public by default, while class memebers are private by default. So you should put the functions inside the struct, or equivalently make it a class.

This is what happens when I create a class in my IDE.

I use the class wizard to do it. The IDE creates a header file & a .cpp file which have the same name as the class. So stack.h & stack.cpp.

When I declare a member function in the header file, it automatically creates a stub function in the .cpp file

stack.h
void createstack(stacktype &stack);

stack.cpp
1
2
3
4
void stack::createstack(stacktype &stack)  //notice the scope resolution operator ::
{
	//your code here
}


The scope resolution operator is very important, probably the cause of your errors.

The file with the main() function, is named after the application - so you could call it MyApp.cpp or anything you like.

With the includes, stack.h has to be included in stack.cpp (obviously) and in any other file that uses a stack object.

So have a go using the IDE (At least once), you will see what it is supposed to look like. If you don't routinely use an IDE, then you will know what you are aiming for.

My IDE has a bunch of other features as well, there are shortcut keys to swap from declaration (header file) to implementation (.cpp file), you have them side by side on the screen, there are kinds of things you can do quickly & easily.

I use KDevelop or QtCreator, depending on what frame of mind I am in, they have similar features.

My OS is Fedora 17 (Linux)

I would recommend Linux for anyone who is keen on IT, because there is untold quality stuff available fro free. There are all kinds of programming languages, and 20,000 apps for other things - ALL FREE

I am not saying get rid of your windows OS, there are probably something you wish to run on it. Have both. Linux needs it's own disk partition, although it is probably better with it's own disk. When I had a PC, I had 2 removable hard drive bays, so I could chop & change as much as I wanted. Now I have a laptop that has 2 500Gb drives.

Hope all goes well .
There's nothing wrong with his code that I can see (at least that would cause compilation problems.) He does do a reprehensible thing by placing a 'using' statement in a header file, but I don't think that's causing the problem -- he could certainly try taking it out, though. Worked fine using the mingw port.
@OP: if you changed your code and got errors you should show the updated code

@TheIdeasMan:
> In the header file, you have a stack struct with functions outside of it...
c++ is not java. We can have functions if we want.
>
1
2
3
4
void stack::createstack(stacktype &stack)  //notice the scope resolution operator ::
{
	//your code here
}
¿why are you receiving an object? If you make it a member you ought to use your state. Also, considering the name, it may be a constructor.
Last edited on
Ideasman, thank you so much for the great reply. I've been shying away from using IDEs because, while they do make things much easier, I'm trying to understand every part of the process. With codeblocks, the IDE I'm using, when I start a new program it steps me through a "New Program Wizard" that seems to automate several steps; I'm not quite sure exactly what it does.

That being said, I just used code blocks on the program that inspired this thread, and it works perfectly.

Your Linux suggestion is timely: I just installed it last week on my second hard drive. It's the latest version of Ubuntu. I think it's high time I get comfortable using it, are there any books or online tutorials/guides that you would suggest for a Linux noob?

I changed the struct into a class and popped the function defs inside it, but I'm still getting the same errors when I take another go at g++.
Last edited on
@ne555

I was suggesting to the OP to put everything into a class, that is make the functions member functions.

For the createstack function, I just copied the OP's function - I didn't look at the details of it. That would have been a more complete answer as you have shown. My intention was to show what a member function stub looked like.

The overall purpose of my post was to put forward a more conventional idea on the layout / organisation of files / classes / functions etc. Also I would observe that just because code compiles and runs correctly doesn't mean that it couldn't be organised better.

loot wrote:
I've been shying away from using IDEs because, while they do make things much easier, I'm trying to understand every part of the process.


That is really good, however I found it was good to use the IDE, so that I could see what the conventional layout of code / files etc. When you understand how it all works, then you do whatever you like. If you do everything from the shell (cmd line) then it is easy to spend a lot of time trying to figure stuff out. Sure the outcome is great - you now know in detail how it works. I am just saying that using the IDE briefly might be a tool to help figure stuff out more quickly.

Two examples of this are the compiler options, and make files.

The gcc ( g++) complier has a zillion options - sure you only need a few of them, but then I see all the options the IDE uses to compile my project, and I think "How long would it have taken me to figure out that I needed those options."

So then I could go back and look at each option the IDE used, and ask myself what does each one do, and why was it necessary?

Same thing with make files, My IDE produces a make file that is several pages long, just for a fairly simple project. How long would have it taken me to figure that out? I already have a basic understanding of how makefiles work, and if I wanted to, I could analyse the whole thing and learn what it is doing in detail.

loot wrote:
are there any books or online tutorials/guides that you would suggest for a Linux noob?


There is
www.linuxquestions.org
they have forums for nearly every sort of linux distro, there is hardware forums, and a programming one as well. If you put C++ in the title of your thread, you will get replies from a bunch of real knowledgeable industry guys. There are real knowledgeable guys here too, but why not get twice the feedback?


loot wrote:
I changed the struct into a class and popped the function defs inside it, but I'm still getting the same errors when I take another go at g++.


Post your new code, and the compiler output. There are plenty of guys & girls raring to go, to help you out.

As I mentioned earlier, I use KDevelop & QtCreator. KDevelop is supposed to be the most mature & well supported IDE in the Linux world (There all sorts of other ones, which one suits best is up to the individual). It can be used with all sorts of languages & technologies including Qt. Qt is a GUI development system that can cross compile to a number of different OS including Linux, Windows & Mac, and some mobile phones like Android. I use QtCreator IDE for this, because it is an IDE specifically designed for the Qt System.

Hope all goes well, have a great day :)

Topic archived. No new replies allowed.