title: c++ header files, Undefined symbols for architecture x86_64
body: <p>I'm trying to build a program to store student grades in C++. I'm receiving the following error when compiling:</p>
  
  <pre><code>Undefined symbols for architecture x86_64: "grade1(Student_records const&amp;)", referenced from:
   _main in gradereport-a0007a.o
  
   "compare(Student_records const&amp;, Student_records const&amp;)", 
  
  referenced from: _main in gradereport-a0007a.o
  
  "read_info(std::__1::basic_istream&lt;char, std::__1::char_traits&lt;char&gt; &gt;&amp;, Student_records&amp;)", 
  
  referenced from: _main in gradereport-a0007a.o
  
  ld: symbol(s) not found for architecture x86_64
  </code></pre>
  
  <p>The command I have been (trying) to use to compile: g++ gradereport.cpp</p>
  
  <p>The told me that something about my read_info, compare, and grade1 functions were wrong (improperly defined). But, I cannot seem to find the issue.</p>
  
  <p>From reading through prior posts on "undefined symbols" issues, it seems that either (a) my function declarations do not match or (b) I need to compile multiple files "at the same time" (for lack of a better phrase). I'm pretty sure it is not (a). If (b), how precisely would I accomplish this task? Also, if anybody has any basic criticism, I would love to hear it. Thanks in advance.</p>
  
  <p>Here's my code:</p>
  
  <p>gradereport.cpp</p>
  
  <pre><code>#include&lt;iostream&gt;
  #include&lt;ios&gt;
  #include&lt;iomanip&gt;
  #include&lt;algorithm&gt;
  #include&lt;vector&gt;
  #include&lt;stdexcept&gt;
  #include "student_records.h"
  #include "Grades.h"
  
  using std::cout;
  using std::endl;
  using std::vector;
  using std::cout;
  using std::cin;
  using std::string;
  using std::max;
  using std::domain_error;
  
  int main()
  {
  
      vector&lt;Student_records&gt; students; 
      Student_records record; 
      string::size_type maxlen = 0;
  
      while(read_info(cin, record))
      {
  
          maxlen = max(maxlen, record.name.size()); // finds the longest name
          students.push_back(record); // enters each record into the vector
  
      }
  
      sort(students.begin(), students.end(), compare); 
      for(vector&lt;Student_records&gt;::size_type i = 0; i != students.size(); ++i)
      {
  
          cout &lt;&lt; students[i].name
              &lt;&lt; string(maxlen + 1 - students[i].name.size(), ' ');
  
          try
          {
  
              double final_grade = grade1(students[i]);
              /* need to define grade function:
                  1) unpack grades;
                  2) find homework grades;
                  3) find final grade;
              */
              cout &lt;&lt; final_grade
  
          }
  
          catch(domain_error e)
          {
  
              cout &lt;&lt; e.what();
  
          }
  
          cout &lt;&lt; endl;
  
      }
  
      return 0;
  
  }
  </code></pre>
  
  <p>student_records.h</p>
  
  <pre><code>#ifndef GUARD_STUDENT_RECORDS
  #define GUARD_STUDENT_RECORDS
  
  #include&lt;iostream&gt;
  #include&lt;string&gt;
  #include&lt;vector&gt;
  
  struct Student_records
  {
  
      std::string name;
      double midterm, final;
      std::vector&lt;double&gt; homeworks;
  
  };
  
  bool compare(const Student_records&amp;, const Student_records&amp;);
  std::istream&amp; read_info(std::istream&amp;, Student_records&amp;);
  std::istream&amp; read_homework(std::istream&amp;, std::vector&lt;double&gt;&amp;);
  
  #endif
  </code></pre>
  
  <p>student_records.cpp</p>
  
  <pre><code>#include "student_records.h"
  
  bool compare(const Student_records&amp; x, const Student_records&amp; y)
  {
  
      return x.name &lt; y.name;
  
  }
  
  std::istream&amp; read_info(istream&amp; is, Student_records&amp; s)
  {
  
      std::cout &lt;&lt; "Enter name, midterm, and final: ";
      is &gt;&gt; s.name &gt;&gt; s.midterm &gt;&gt; s.final;
  
      read_homework(std::istream&amp;, std::vector&lt;double&gt;&amp;);
  
      return is;
  
  }
  
  std::istream&amp; read_homework(std::istream&amp; in, std::vector&lt;double&gt;&amp; homework)
  {
  
      cout &lt;&lt; "Enter homework: ";
  
      if(in)
      {
          hw.clear()
  
          double x;
          while(in &gt;&gt; x)
              homework.push_back(x);
  
          in.clear();
      }
  
      return in;
  
  }
  </code></pre>
  
  <p>Grades.h</p>
  
  <pre><code>#ifndef GUARD_GRADES
  #define GUARD_GRADES
  
  #include&lt;iostream&gt;
  #include&lt;vector&gt;
  #include&lt;string&gt;
  #include "student_records.h"
  
  double grade1(const Student_records&amp;);
  double grade2(double, double, std::vector&lt;double&gt;);
  double median(std::vector&lt;double&gt;);
  
  #endif
  </code></pre>
  
  <p>Grades.cpp</p>
  
  <pre><code>#include&lt;stdexcept&gt;
  #include&lt;vector&gt;
  #include "grades.h"
  #include "Student_records.h"
  
  using std::domain_error;
  using std::vector;
  
  double grade2(double midterm, double final, std::vector&lt;double&gt; homework)
  {
  
      double final_homework_grade;
  
      final_homework_grade = median(homework);
  
      return .4 * final_homework_grade + .4 * final + .2 * midterm;
  
  }
  
  double median(vector&lt;double&gt; homework)
  {
  
      typedef vector&lt;double&gt;::size_type vec_sz;
  
      vec_sz size = homework.size();
  
      if(size == 0)
          throw domain_error("student has done no homework");
  
      sort(homework.begin(), homework.end());
  
      return size % 2 == 0 ? ((homework[mid] + homework[mid + 1]) / 2) : homework[mid];
  
  }
  
  double grade1(const Student_records&amp; s) // unpacks grades
  {
  
      return grade2(s.midterm, s.final, s.homework);
  
  }
  </code></pre>