简体   繁体   中英

Undefined reference error with Eclipse (C++)

I have been learning C++, and have been using some test code to debug pieces of a much larger project. I am trying to use an object from another file, but I keep getting an undefined reference error despite having included the appropriate header file. I am using Eclipse with the C++ CDT on Linux. The code looks something like the following:

A.cpp

class A {

   private:

      int i;
      int j;

   public:

      A(int i1, int i2) {
         i = i1;
         j = i2;
      }

      int sum() {
         return (i+j);          
      }
};

ah

#ifndef A_H_
#define A_H_

class A {
   public:
      A(int i1, int i2);
      int sum();
};
#endif

main.cpp

#include <iostream>
#include "a.h"

int main() {
   A a(1,2); //undefined reference to 'A::A(int,int)'
   std::cout << a.sum(); //undefined reference to 'A::sum(void)'
   return 0;
}

Is this a problem with my syntax, or do I need to go digging around in the compiler?

The problem is that main.cpp sees only the definition of the class in the header ah that does not contain definitions of the constructor and of the member function.

in A.cpp these function are defined but by default they are defined as inline functions. So again main.cpp does not see their definitions.

Take into account that according to the C++ Standard (3.2 One definition rule)

6 There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then

(6.1) — each definition of D shall consist of the same sequence of tokens ; and

So in A.cpp you should write

#include "a.h"


  A::A(int i1, int i2) {
     i = i1;
     j = i2;
  }

  int A::sum() {
     return (i+j);          
  }

Also a class definition shall be ended with a semicolon.

That's not how you split the public interface and private implementation of a class in C++.

In order for this code in main to compile

   A a(1,2);

the compiler needs to already know the size of A - this is because the storage is allocated locally, even if the constructor called to initialize it is defined elsewhere.

You can avoid this coupling by using pointers (preferably smart ones) or the pimpl idiom, but that's the default.

This means the definition of your class in the header must be

class A {
    int i;
    int j;

public:
    A(int i1, int i2);
    int sum();
};

(note the ' at the end of the class definition, which is important - you also need to be sure you terminated your include guards with an #endif ).

The implementation cpp file should then look like

#include "a.h"

A::A(int i1, int i2) : i(i1), j(i2)
{
}

int A::sum()
{
  return (i+j);          
}

You're only allowed to define A once, so you can't have a different definition in the header and in the implementation file.

Now those issues are fixed: if your original error persists, the residual problem is probably with your compile/link setup.

The stuff that everyone is saying about definitions is true. But there are a couple of other problems as well:

  • you need a semicolon ; after the closing brace of a class definition
  • you need an #endif directive after the #ifndef (usually goes at the very end of a header file)
  • even with #include <iostream> , cout does not get exported to the top-level namespace. You have to refer to it as std::cout

Here's a complete working example. It's one file, but you can split it up yourself if you want to:

#ifndef A_H_
#define A_H_

class A {
   private:

      int i;
      int j;

   public:
      A(int i1, int i2);
      int sum();
};
#endif

A::A(int i1, int i2) {
    i = i1;
    j = i2;
}

int A::sum() {
    return (i+j);          
}

#include <iostream>

int main() {
   A a(1,2);
   std::cout << a.sum();
   return 0;
}

Try it out online yourself

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM