This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 2 years ago.
I'm having some difficulty reproducing an example program of Object-Oriented Programming Using C++ described in "Encapsulation and Type Extensibility."
For simplicity's sake, I've cut out most of the code to focus on the specific error at hand:
#include <iostream> // Access standard IO library
#include <string> //Access type 'string'
using namespace std; //Use standard library namespace
const int max_length = 255;
class my_string {
public:
void assign(const char* st);
int length() const { return len; }
void print() const
{ cout << s << "\nLength: " << len << endl; }
private:
char s[max_length];
int len;
};
int main()
{
my_string one;
one.assign("I'm sorry Dave, I'm afraid I can't do that.");
one.print();
system("PAUSE");
}
When I try to compile, I get the error message:
[Linker error] undefined reference to 'my_string::assign(char const*)'
I'm not sure what I'm doing wrong. My best guess is that assign is incorrectly defined, since the main() block seems fine.
Edit:
The complete example as written in the book is:
In file string1.cpp
const int max_len = 255;
class my_string {
public:
void assign(const char* st);
int length() const { return len; }
void print() const
{ cout << s << "\nLength: " << len << endl; }
private:
char s[max_length];
int len;
};
int main()
{
my_string one, two;
char three[40] = {"My name is Charles Babbage."};
one.assign("My name is Alan Turing.");
two.assign(three);
cout << three;
cout << "\nLength: " << strlen(three) << endl;
if (one.length() <= two.length())
one.print();
else
two.print();
}
Linking and compiling errors are two different things. A compiler error means that you did something wrong in the syntax.
A linking error tells you that there is a part missing when the linker tries to put your program together.
[Linker error] undefined reference to 'my_string::assign(char const*)'
This error tells you that somewhere the promise was made to the compiler that my_string::assign(char const*) exists and can be used (by a declaration void assign(const char* st);). But in the linking step the linker cannot find that function.
If the error references a function that you have written, then you might have forgotten the definition of it or have mismatching signature between declaration and definition.
The compiler can't find it's definition.
Usually there is a header file (.h) where the class' declaration is put, including as less as possible and a source file (.cpp) that includes all the definitions.
The header file declarations tells the compiler which methods shall be available (as a promise),
the source file should contain the definition of the functions that are declared in the header file.
If they aren't defined, meaning there is no body for that function, it can't be executed. In your book, the code is both declared and defined, by writing the methods inside the class' definition.
You could do the same:
public:
void assign(const char* st) {
/* implementations of the assign method here
(or leave it empty for this example, but rather don't)*/
};
int length() const { return len; };
...
Related
This question already has answers here:
Explanation of function pointers
(4 answers)
Closed 8 months ago.
I have the following scenario: I have a third party library and a header associated with it, that I'm using in my project. I completed my project and now I'm unit testing my code and I want to use a stub library, created by myself, for the third party library.
The header for the third party library contains structures that looks like this:
typedef struct{
int (*init)(int * var);
void (*close)(void);
} AInterface
To create my stub version, I created a .cpp file, in which I include the header, and started to implement it like this:
int AInterface::*init(int* var)
{
return 0;
}
void AInterface::*close(void)
{}
But when I compile my code I get the following error: "stub.cpp:76:33: error: cannot declare pointer to ‘void’ member
void AInterface::*close(void)"
I have searched the internet but with no success.
My questions are:
what I am doing wrong here?
is there another way to implement the stub?
I have also tried to implement the stub like this:
int initAInterface(int * var);
int (AInterface::*init)(int * var) = &initAInterface;
int initAInterface(int* var)
{
return 0;
}
But I get the following error:
error: cannot convert ‘int (*)(int*)’ to ‘int (AInterface::*)(int*)’ in initialization
int (AInterface::*init)(int* var) = &initAInterface;
Also I have no main in my stub .cpp file.
Those are function pointers and expect you to give static functions to them, then pass the struct to the library
//#################################################################
//Library header
typedef struct {
int (*init)(int* var);
void (*close)(void);
} AInterface;
//#################################################################
//A CPP file somewhere
//You might need extern "C" if you're mixing C and C++
#include "LibraryHeader.h"
int myInitFuction(int* var)
{
std::cout << "I wrote the init function for this" << std::endl;
return 0;
}
void myCloseFunction(void){
std::cout << "I wrote the close function for this" << std::endl;
}
//Or some other function doesn't need to be main if it's not the entry point
int main()
{
AInterface myInterface;
myInterface.init = myInitFuction;
myInterface.close = myCloseFunction;
SomeLibraryFuction(&myInterface);
}
This question already has answers here:
C++ Multiple Definition of Struct
(2 answers)
Why is there no multiple definition error when you define a class in a header file?
(3 answers)
Closed 1 year ago.
C++ translator seems uses correct declared structs of the same name, but then linker mismatches them without any warning or error! And this also leads to UB, because at least inappropriate ctor/dtor are used for the memory region.
Here is minimal sandbox code. Each struct Test should be treated as some internal non-public structure used only in one own .cpp file.
file1.cpp
#include <iostream>
using namespace std;
void someFunc();
struct Test
{
Test() { std::cout << "1 "; }
~Test() { std::cout << "~1" << std::endl; }
};
int main()
{
{
Test test;
}
someFunc();
return 0;
}
file2.cpp
#include <iostream>
struct Test {
Test() { std::cout << "2 "; }
~Test() { std::cout << "~2" << std::endl; }
};
void someFunc() {
Test test;
}
(Downloadable and buildable CMake-project just in case: https://file.io/dzafv409B2t0)
Output will be:
1 ~1
1 ~1
So, I expected:
Successful build with output: 1 ~1 2 ~2
Or failed build with multiple definition error
Yes, I can resolve the problem if:
Rename the struct
Put the struct into anonymous namespace - force internal linkage
...but this doesn't answer the main question:
Why linker behaves so? Why does it silently links to first available matching symbol (among several) instead of reporting multiple definition error?
Update: As I understood, this mechanism allows to include header with class declaration (with inline code) into several different source files without multiple definition problem.
This question has derived from this one.
I have a working program which must be split into multiple parts. In this program is needed to use a variable (now it's a GTK+ one :P) many times in parts of the program that will end up in separated .cpp files.
So, I made a simple example to understand how to make variables available to the program parts. A modified version of the previous code would be:
#include <iostream>
using namespace std;
int entero = 10;
void function()
{
cout<<entero<<endl;
//action1...;
}
void separated_function()
{
cout<<entero<<endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
It is needed to split the code correctly, to have function(), another_function() and main() in separated .cpp files,and make entero avaliable to all of them... BUT:
In the previous question #NeilKirk commented:Do not use global variables. Put the required state into a struct or class, and pass it to functions as necessary as a parameter (And I also have found many web pages pointing that is not recommended to use global variables).
And, as far I can understand, in the answer provided by #PaulH., he is describing how to make variables avaliable by making them global.
This answer was very useful, it worked fine not only with char arrays, but also with ints, strings and GTK+ variables (or pointers to variables :P).
But since this method is not recommended, I would thank anyone who could show what would be the correct way to split the code passing the variables as a function parameter or some other method more recommended than the - working - global variables one.
I researched about parameters and classes, but I'm a newbie, and I messed the code up with no good result.
You need to give the parameter as a reference if you want the same comportement as a global variable
#include <iostream>
using namespace std;
// renamed the parameter to avoid confusion ('entero' is valid though)
void function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value
//action1...;
}
void separated_function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value again
//action2...;
}
int main( int argc, char *argv[] )
{
int entero = 10; // initializing the variable
// give the parameter by reference => the functions will be able to modify its value
function(entero);
separated_function(entero);
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
output:
10
11
12
Defining a class or struct in a header file is the way to go, then include the header file in all source files that needs the classes or structures. You can also place function prototypes or preprocessor macros in header files if they are needed by multiple source files, as well as variable declarations (e.g. extern int some_int_var;) and namespace declarations.
You will not get multiple definition errors from defining the classes, because classes is a concept for the compiler to handle, classes themselves are never passed on for the linker where multiple definition errors occurs.
Lets take a simple example, with one header file and two source files.
First the header file, e.g. myheader.h:
#ifndef MYHEADER_H
#define MYHEADER_H
// The above is called include guards (https://en.wikipedia.org/wiki/Include_guard)
// and are used to protect the header file from being included
// by the same source file twice
// Define a namespace
namespace foo
{
// Define a class
class my_class
{
public:
my_class(int val)
: value_(val)
{}
int get_value() const
{
return value_;
}
void set_value(const int val)
{
value_ = val;
}
private:
int value_;
};
// Declare a function prototype
void bar(my_class& v);
}
#endif // MYHEADER_H
The above header file defines a namespace foo and in the namespace a class my_class and a function bar.
(The namespace is strictly not necessary for a simple program like this, but for larger projects it becomes more needed.)
Then the first source file, e.g. main.cpp:
#include <iostream>
#include "myheader.h" // Include our own header file
int main()
{
using namespace foo;
my_class my_object(123); // Create an instance of the class
bar(my_object); // Call the function
std::cout << "In main(), value is " << my_object.get_value() << '\n';
// All done
}
And finally the second source file, e.g. bar.cpp:
#include <iostream>
#include "myheader.h"
void foo::bar(foo::my_class& val)
{
std::cout << "In foo::bar(), value is " << val.get_value() << '\n';
val.set_value(456);
}
Put all three files in the same project, and build. You should now get an executable program that outputs
In foo::bar(), value is 123
In main(), value is 456
I prefer to provide a functional interface to global data.
.h file:
extern int get_entero();
extern void set_entero(int v);
.cpp file:
static int entero = 10;
int get_entero()
{
return entero;
}
void set_entero(int v)
{
entero = v;
}
Then, everywhere else, use those functions.
#include "the_h_file"
void function()
{
cout << get_entero() << endl;
//action1...;
}
void separated_function()
{
cout << get_entero() << endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<< get_entero() <<endl;
//something else with the mentioned variables...;
return 0;
}
If you do not plan to modify the variable, it is generally ok to make it global. However, it is best to declare it with the const keyword to signal the compiler that it should not be modified, like so:
const int ENTERO = 10;
If you are using multiple cpp files, also consider using a header file for your structures and function declarations.
If you are planning on modifying the variable, just pass it around in function parameters.
I am new to templates in c++.
i was trying some small programs.
CPP [80]> cat 000001.cpp 000001.hpp
#include <iostream>
#include <string>
#include "000001.hpp"
int main()
{
int i = 42;
std::cout << "max(7,i): " << ::max(7,i) << std::endl;
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1,f2): " << ::max(f1,f2) << std::endl;
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1,s2): " << ::max(s1,s2) << std::endl;
}
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
when i compile this program:
i get an error below:
CPP [78]> /opt/aCC/bin/aCC -AA 000001.cpp
Error (future) 229: "/opt/aCC/include_std/string.cc", line 164 # "Ambiguous overloaded function call; a
function match was not found that was strictly best for ALL arguments. Two functions that matched
best for some arguments (but not all) were "const unsigned long &max<unsigned long>(const unsigned
long &,const unsigned long &)" ["000001.hpp", line 2] and "const unsigned long &std::max<unsigned
long>(const unsigned long &,const unsigned long &)" ["/opt/aCC/include_std/algorithm", line 1762]."
Choosing "const unsigned long &max<unsigned long>(const unsigned long &,const unsigned long &)"
["000001.hpp", line 2] for resolving ambiguity.
_C_data = _C_getRep (max (_RW::__rw_new_capacity (0, this),
^^^
Warning: 1 future errors were detected and ignored. Add a '+p' option to detect and fix them before they become fatal errors in a future release. Behavior of this ill-formed program is not guaranteed to match that of a well-formed program
Could nybody please tell me what exactly the error is?
You are probably including <iostream.h> instead of <iostream> somewhere. The former hasn't existed for some time now, but for compatibility reasons, you compiler still accepts the include and replaces it with
#include <iostream>
using namespace std;
This causes std::max to be brought to the global namespace, thus resulting in an ambiguity. Replace <iostream.h> with <iostream> or rename your max function and the problem should disappear.
Edit: You've apparently fixed the include, but I bet you still have using namespace std; somewhere. You need to get rid of that. In fact you should never use using namespace in the global scope.
Edit: You might also have using std::max somewhere. You need to get rid of it too.
The code you've posted compiles just fine, there must be something else that is wrong inside "000001.hpp". Can you post the contents of that file too?
Edit: If you do as avakar says but the problem persists, that must be due to some problem with your compiler. There are two obvious workarounds I can think of: rename your max function to something else, or put it in a namespace:
namespace Foo
{
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
}
int main()
{
int i = 42;
std::cout << "max(7,i): " << Foo::max(7,i) << std::endl;
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1,f2): " << Foo::max(f1,f2) << std::endl;
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1,s2): " << Foo::max(s1,s2) << std::endl;
}
I don't know which compiler you are using but the second error tells you that the two following functions are clashing :
::max
std::max
It seems really weird, you may have a using namespace std; somewhere or worse, that one of your include use iostream.h as noted in the first error. Could you give more information about your compiler/toolchain and the content of your .hpp file?
It says that two definitions for
max<unsigned long>
were found. One definition is in 000001.hpp and the other is in /opt/aCC/include_std/algorithm. The compiler chose the one in 000001.hpp for now, so no error is present now. But it says that these two definitions may cause errors in the future.
I don't know if this causes the problem, but anyhow; you shouldnt use the name max for your global (or local) function as it is a part of STL.
Playing around with MSVC++ 2005, I noticed that if the same class is defined several times, the program still happily links, even at the highest warning level. I find it surprising, how comes this is not an error?
module_a.cpp:
#include <iostream>
struct Foo {
const char * Bar() { return "MODULE_A"; }
};
void TestA() { std::cout << "TestA: " << Foo().Bar() << std::endl; }
module_b.cpp:
#include <iostream>
struct Foo {
const char * Bar() { return "MODULE_B"; }
};
void TestB() { std::cout << "TestB: " << Foo().Bar() << std::endl; }
main.cpp:
void TestA();
void TestB();
int main() {
TestA();
TestB();
}
And the output is:
TestA: MODULE_A
TestB: MODULE_A
It is an error - the code breaks the C++ One Definition Rule. If you do that, the standard says you get undefined behaviour.
The code links, because if you had:
struct Foo {
const char * Bar() { return "MODULE_B"; }
};
in both modules there would NOT be a ODR violation - after all, this is basically what #including a header does. The violation comes because your definitions are different ( the other one contains the string "MODULE_A") but there is no way for the linker (which just looks at class/function names) to detect this.
The compiler might consider that the object is useless besides its use in Test#() function and hence inlines the whole thing. That way, the linker would never see that either class even existed ! Just an idea, though.
Or somehow, linking between TestA and class Foo[#] would be done inside compilation. There would be a conflict if linker was looking for class Foo (multiple definition), but the linker simply does not look for it !
Do you have linking errors if compiling in debug mode with no optimizations enabled ?