www.digitalmars.com         C & C++   DMDScript  

c++ - Newbie needs help with header files

reply Brett O'Hare <Brett_member pathlink.com> writes:
Hello.

I am just starting to learn about partitioning C++ programs into header files,
source files, etc.  Here is a very basic example (for illustrative purposes) and
then I'll explain what my problem is-- 

//Cube.h -- header file
int Cube(int);

//Cube.cpp -- source file
#include "Cube.h"
int Cube(int number)
{
return number * number * number;
}

//CubeTest.cpp  -- main program
#include <iostream>
#include "Cube.h"

int main()
{
int numberCubed = Cube(3);
std::cout << "The number cubed is " << numberCubed << std::endl;
return 0;
}

The problem is when I try to compile this using the Digital Mars compiler:
dmc CubeTest.cpp

I get the following error:
--------------------------------------
link cubetest,,,user32+kernel32/noi;

OPTLINK (R) for Win32  Release 7.50B1
Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved

cubetest.obj(cubetest) 
Error 42: Symbol Undefined ?Cube  YAHH Z (int cdecl Cube(int ))

--- errorlevel 1
Process dmc exited with code 1
--------------------------------------

What seems to be happening is that the source file, Cube.cpp, isn't being "seen"
(linked or whatever the appropriate term is).  If I include it directly,
#include "Cube.cpp", everything works as expected.

I guess my question is is there a flag I should be using when compiling to
properly link the three files together, or am I not using header files
correctly?  My understanding was that header files contain the declaration,
while the source files contain the definitions.

Any help would be greatly appreciated!

(Also, I apologize for the simple-mindedness of this example... but we all have
to start somewhere, right?)
Jul 05 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
No apologies necessary, it's all weird as hell when you start. ;)

You need to compile both implementation files. This can be done separately, as
in:

    dmc -c CubeTest.cpp
    dmc -c Cube.cpp
    dmc CubeTest.obj Cube.obj

1. -c - says to the compiler to "compile only". In other words, it compiles the
files from .cpp to object file format .obj. The linking step, which takes .obj
into the final .exe form, is not done.
2. The third command gets the compiler to do the link step. The first .obj file
specified will be used as the base-name for the executable, so it'll make
CubeTest.exe

There's another way to do it, which is all in one, as in:

    dmc CudeTest.cpp Cube.cpp





"Brett O'Hare" <Brett_member pathlink.com> wrote in message
news:cccoq2$kqg$1 digitaldaemon.com...
 Hello.

 I am just starting to learn about partitioning C++ programs into header files,
 source files, etc.  Here is a very basic example (for illustrative purposes)
and
 then I'll explain what my problem is-- 

 //Cube.h -- header file
 int Cube(int);

 //Cube.cpp -- source file
 #include "Cube.h"
 int Cube(int number)
 {
 return number * number * number;
 }

 //CubeTest.cpp  -- main program
 #include <iostream>
 #include "Cube.h"

 int main()
 {
 int numberCubed = Cube(3);
 std::cout << "The number cubed is " << numberCubed << std::endl;
 return 0;
 }

 The problem is when I try to compile this using the Digital Mars compiler:
 dmc CubeTest.cpp

 I get the following error:
 --------------------------------------
 link cubetest,,,user32+kernel32/noi;

 OPTLINK (R) for Win32  Release 7.50B1
 Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved

 cubetest.obj(cubetest)
 Error 42: Symbol Undefined ?Cube  YAHH Z (int cdecl Cube(int ))

 --- errorlevel 1
 Process dmc exited with code 1
 --------------------------------------

 What seems to be happening is that the source file, Cube.cpp, isn't being
"seen"
 (linked or whatever the appropriate term is).  If I include it directly,
 #include "Cube.cpp", everything works as expected.

 I guess my question is is there a flag I should be using when compiling to
 properly link the three files together, or am I not using header files
 correctly?  My understanding was that header files contain the declaration,
 while the source files contain the definitions.

 Any help would be greatly appreciated!

 (Also, I apologize for the simple-mindedness of this example... but we all have
 to start somewhere, right?)
Jul 05 2004
next sibling parent Brett O'Hare <Brett_member pathlink.com> writes:
In article <ccd5gj$15o5$1 digitaldaemon.com>, Matthew says...
No apologies necessary, it's all weird as hell when you start. ;)
Yes, yes it is!
You need to compile both implementation files. This can be done separately, as
in:

    dmc -c CubeTest.cpp
    dmc -c Cube.cpp
    dmc CubeTest.obj Cube.obj

1. -c - says to the compiler to "compile only". In other words, it compiles the
files from .cpp to object file format .obj. The linking step, which takes .obj
into the final .exe form, is not done.
2. The third command gets the compiler to do the link step. The first .obj file
specified will be used as the base-name for the executable, so it'll make
CubeTest.exe

There's another way to do it, which is all in one, as in:

    dmc CudeTest.cpp Cube.cpp
Aha! Up to this point I had been learning from a book using "single file" (I guess you would call it) programs-- all the functions, class, logic, etc, in one file. Compiling that worked as a one step process. Needless to say, I was at a loss when things started becoming more modular (as in creating header files). Thanks for the reply and the explanation.
Jul 05 2004
prev sibling parent reply Brett O'Hare <Brett_member pathlink.com> writes:
You need to compile both implementation files. This can be done separately, as
in:

    dmc -c CubeTest.cpp
    dmc -c Cube.cpp
    dmc CubeTest.obj Cube.obj

1. -c - says to the compiler to "compile only". In other words, it compiles the
files from .cpp to object file format .obj. The linking step, which takes .obj
into the final .exe form, is not done.
2. The third command gets the compiler to do the link step. The first .obj file
specified will be used as the base-name for the executable, so it'll make
CubeTest.exe

There's another way to do it, which is all in one, as in:

    dmc CudeTest.cpp Cube.cpp
I've been playing around with this a bit more and I am still not understanding something. Using this method of compiling, I can comment out all header includes and the program still compiles and runs as expected. Functionally, it seems the equivalent of adding '#include "cube.cpp"' to cubetest.cpp; the header file doesn't seem to be used at all. My understanding is that a header file should "know" to get its definitions from the associated source file, so when you include a header file in program, all functions, etc declared in the header are available for use. It is the linking the header to the source file part that I am having the trouble with. My question is: how do I properly link and use a header file? Thanks
Jul 06 2004
parent reply Arjan Knepper <arjan ask.me> writes:
Brett O'Hare wrote:
You need to compile both implementation files. This can be done separately, as
in:

   dmc -c CubeTest.cpp
   dmc -c Cube.cpp
   dmc CubeTest.obj Cube.obj

1. -c - says to the compiler to "compile only". In other words, it compiles the
files from .cpp to object file format .obj. The linking step, which takes .obj
into the final .exe form, is not done.
2. The third command gets the compiler to do the link step. The first .obj file
specified will be used as the base-name for the executable, so it'll make
CubeTest.exe

There's another way to do it, which is all in one, as in:

   dmc CudeTest.cpp Cube.cpp
I've been playing around with this a bit more and I am still not understanding something. Using this method of compiling, I can comment out all header includes and the program still compiles and runs as expected. Functionally, it seems the equivalent of adding '#include "cube.cpp"' to cubetest.cpp; the header file doesn't seem to be used at all. My understanding is that a header file should "know" to get its definitions from the associated source file, so when you include a header file in program, all functions, etc declared in the header are available for use. It is the linking the header to the source file part that I am having the trouble with. My question is: how do I properly link and use a header file? Thanks
You're mixing up a little: In header files you declare and/or define variables, const, objects etc. In cpp file you implement the objects, initialize variables etc. You normally never include .cpp files into other files. Only include .h/.hpp/.inl files into other .h .hpp or .cpp files. The compiler reads the .cpp file and searches for definitions and/or declarations of the variabels, const, object etc in the header files included in the .cpp file if they are NOT in the .cpp itself. (also in the header files included by other header files) This is because the compiler has to know certain properties of the object, variables etc. (e.g. the size, whether or not it is const etc) When you remove all includes from a .cpp file and the .cpp file has variables of object in it not defined in the .cpp file, the compiler doesn;t know how to get the information about those objects, variables etc and will bark about it. Hope this helps a little. Arjan example: file test.h: ----------------------- #ifndef TEST_H #define TEST_H class ObjectTest; // declaration of a class ObjectTest // No definition yet #endif ----------------------- file test.hpp ----------------------- #ifndef TEST_HPP #define TEST_HPP #include "test.h" // include the declaration // not strictly neccesary because when de define // a object we declare it as well class ObjectTest // defintion of class ObjectTest, know the size { // is known. private : int a_int; public : ObjectTest ( int ); }; #endif ----------------------- file test.cpp ----------------------- #include "test.hpp" // include the definition and implement the // ObjectTest class ObjectTest :: ObjectTest ( int _a ) { a_int = _a; }
Jul 06 2004
parent reply Brett O'Hare <Brett_member pathlink.com> writes:
In article <ccehp1$d2g$1 digitaldaemon.com>, Arjan Knepper says...

You're mixing up a little:

In header files you declare and/or define variables, const, objects etc.
In cpp file you implement the objects, initialize variables etc.

You normally never include .cpp files into other files. Only include 
.h/.hpp/.inl files into other .h .hpp or .cpp files.
..
Hope this helps a little.
Arjan

example:

file test.h:
-----------------------
#ifndef TEST_H
#define TEST_H


class ObjectTest;	// declaration of a class ObjectTest
                         // No definition yet

#endif
-----------------------

file test.hpp
-----------------------
#ifndef TEST_HPP
#define TEST_HPP

#include "test.h"      // include the declaration
                        // not strictly neccesary because when de define
                        // a object we declare it as well

class  ObjectTest      // defintion of class ObjectTest, know the 
size 		{                      // is known.
    private :
       int          a_int;

    public  :
       ObjectTest ( int );
};

#endif
-----------------------
file test.cpp
-----------------------
#include "test.hpp"    // include the definition and implement the 

                        // ObjectTest class

ObjectTest :: ObjectTest ( int  _a )
{
    a_int = _a;
}
O.K. this explanation and example makes sense to me. I think the source of my confusion is the book I am using to learn C++, "Accelerated C++: Practical Programming by Example". It uses the terminology a little differently and the implementation completely differently, if I am understanding it correctly. An example from the book (part of a grading program): ---------------- grade.h // what the book calls, a header file ---------------- #ifndef GRADE_H #define GRADE_H #include <vector> #include "Student_info.h" double grade(double, double, double); // etc... #endif --------------- grade.cpp //what the book calls a "source file" for the header --------------- // other includes #include "grade.h" double grade(double midterm, double final, doubel homework) { return 0.2 * midterm + 0.4 * final + 0.4 homework; } // rest of function definitions... ------------------ studentgrades.cpp ------------------ // other #includes #include "grade.h" int main() { // etc... } In the book's example it invokes the grades.h file directly, which is what I didn't understand. I couldn't figure out how you got from the declarations in grade.h to the definitions in grade.cpp. The short answer seems to be you can't. Is this a book error, or am I still missing something significant? Thanks.
Jul 06 2004
parent reply Arjan Knepper <arjan ask.me> writes:
Brett O'Hare wrote:
 In article <ccehp1$d2g$1 digitaldaemon.com>, Arjan Knepper says...
 
 
You're mixing up a little:

In header files you declare and/or define variables, const, objects etc.
In cpp file you implement the objects, initialize variables etc.

You normally never include .cpp files into other files. Only include 
.h/.hpp/.inl files into other .h .hpp or .cpp files.
..
Hope this helps a little.
Arjan

example:

file test.h:
-----------------------
#ifndef TEST_H
#define TEST_H


class ObjectTest;	// declaration of a class ObjectTest
                        // No definition yet

#endif
-----------------------

file test.hpp
-----------------------
#ifndef TEST_HPP
#define TEST_HPP

#include "test.h"      // include the declaration
                       // not strictly neccesary because when de define
                       // a object we declare it as well

class  ObjectTest      // defintion of class ObjectTest, know the 
size 		{                      // is known.
   private :
      int          a_int;

   public  :
      ObjectTest ( int );
};

#endif
-----------------------
file test.cpp
-----------------------
#include "test.hpp"    // include the definition and implement the 

                       // ObjectTest class

ObjectTest :: ObjectTest ( int  _a )
{
   a_int = _a;
}
O.K. this explanation and example makes sense to me. I think the source of my confusion is the book I am using to learn C++, "Accelerated C++: Practical Programming by Example". It uses the terminology a little differently and the implementation completely differently, if I am understanding it correctly. An example from the book (part of a grading program): ---------------- grade.h // what the book calls, a header file ---------------- #ifndef GRADE_H #define GRADE_H #include <vector> #include "Student_info.h" double grade(double, double, double); // etc... #endif --------------- grade.cpp //what the book calls a "source file" for the header --------------- // other includes #include "grade.h" double grade(double midterm, double final, doubel homework) { return 0.2 * midterm + 0.4 * final + 0.4 homework; } // rest of function definitions... ------------------ studentgrades.cpp ------------------ // other #includes #include "grade.h" int main() { // etc... } In the book's example it invokes the grades.h file directly, which is what I didn't understand. I couldn't figure out how you got from the declarations in grade.h to the definitions in grade.cpp. The short answer seems to be you can't. Is this a book error, or am I still missing something significant? Thanks.
I have that book too, wich page are you refering to? BTW, that book is intended for people with some programming experience iaw if you are complete new to programming in general, it might be a bit to difficult. Arjan
Jul 06 2004
parent Brett O'Hare <Brett_member pathlink.com> writes:
In article <ccf942$1g8r$1 digitaldaemon.com>, Arjan Knepper says...

I have that book too, wich page are you refering to?
Pages 65 - 71, Sections 4.3 through 4.5. I have the 8th printing of the book so the pages maybe slightly different for other printings.
BTW, that book is intended for people with some programming experience 
iaw if you are complete new to programming in general, it might be a bit 
  to difficult.

Arjan
Yes, this book may be a bit beyond me at this point. It is only the second text on the subject I have read. Where it seemed highly rated and used a reportedly different approach to teaching C++ (i.e. teach most useful things instead of most the basic first), I thought I would give it a try. I've re-read the posts in this thread and some other info on the internet, and I think I've got myself straightened out. I was making things more complicated than they really were by confusing header implementation, code modularity, and code compilation. Thanks to all those who responded; I appreciate your help! Brett
Jul 07 2004