Why my inline functions have linking error? - c++

I am learning C++ and currently testing inline functions. If I run my code now I will have linking error, but if I change
inline void Test::print40()
to
void Test::print40()
everything would be fine. Could you explain to me why I have an error and how to use inline function in this case.
// main.cpp file
#include "Test.h"
using namespace std;
int main()
{
Test obj1;
obj1.print40();
}
// Test.cpp file
#include <iostream>
#include "Test.h"
inline void Test::print40()
{
std::cout << "40";
}
// Test.h file
#pragma once
class Test
{
public:
void print40();
};

Inline function definition shall be in each compilation unit where it is ODR used.
On the other hand in your project the compilation unit main does not know that the function is an inline function. So it can not find its definition.
Move this definition from Test.cpp
#pragma once
class Test
{
public:
void print40();
};
inline void Test::print40()
{
std::cout << "40";
}
to the header Test.h.
The module Test.cpp is redundant.
As the function is very simple and short then it could be defined in the class definition as for example
class Test
{
public:
void print40()
{
std::cout << "40";
}
};
In this case it will be an inline function by default.

Related

linking static class member function throws undefined reference error c++

I've gone through many similar threads on this kind of question but I'm still unable to resolve this error. Any help would be appreciated.
/*samp.h header file*/
#include<iostream>
using namespace std;
class test
{
private:
test();
public:
static void const_caller();
};
/*samp.cpp file*/
#include<iostream>
using namespace std;
class test
{
private:
test()
{
cout<<"priv cont called\n";
}
public:
static void const_caller()
{
cout<<"calling priv const\n";
}
};
/*main.cpp file */
#include"samp.h"
using namespace std;
int main(int argc, char **argv)
{
test::const_caller();
}
when I do
g++ samp.cpp main.cpp -o main.out
I get this error
/usr/bin/ld: /tmp/ccHZVIBK.o: in function `main':
main.cpp:(.text+0x14): undefined reference to `test::const_caller()'
which I'm unable to resolve since quite some time now.
In the samp.cpp file you define test class again.
You need to include samp.h header and implement methods of test class:
#include "samp.h"
using namespace std;
test::test()
{
cout << "priv cont called\n";
}
void test::const_caller()
{
cout << "calling priv const\n";
}
With your posted code, the .cpp file contains its own definition of the class that has the same name as the class in the .h file but it is really a different class.
In the .cpp file, you need to use:
test::test()
{
cout<<"priv cont called\n";
}
void test::const_caller()
{
cout<<"calling priv const\n";
}

Cannot create a method in a class

I am new to c++ but have had some experience with java. I am trying to create a class but when i attempt to make a new method in the class I get several error (this is my .cpp file)
//.cpp file
#include "Test.h"
#include "Test.h"
#include <iostream>//unresolved inclusion
using namespace std;
void speak() {
if (happy) {//Symbol hapy could not be resolved
cout << "Meouw!" << endl;
} else {
cout << "Ssssss!" << endl;
}
}
void Test::makeHappy() { // member decleration not found
happy = true;//Symbol hapy could not be resolved
}
void Test::makeSad() { // member decleration not found
happy = false;//Symbol hapy could not be resolved
}
I dont get any errors in my heder file but have included it just in case
#ifndef TEST_H_
#define TEST_H_
class Test {
private:
bool happy;
public:
void makeHappy();
void makeSad();
void speak();
};
#endif /* TEST_H_ */
Finally I have another .cpp file I use which also gets errors
#include <iostream>//unresolved inclusion
#include "Test.h"
#include "Test.cpp"
using namespace std;
int main() {
Test jim;
jim.makeHappy();//method make happy could not be resolved
jim.speak();//method speak could not be resolved
Test bob;
bob.makeSad();//method make happy could not be resolved
bob.speak();//method speak could not be resolved
return 0;
}
This is the new error message I get when compiling
<!-- begin snippet: js hide: false -->
Sorry if this question is to open ended but I just cannot seem to find answers elsewhere.
this is your header file Test.h:
happy member was named bhappy_
for a private member think to add a getter and setter public member functions
#ifndef TEST_H_
#define TEST_H_
class Test {
private:
bool bhappy_;
public:
Test() // ctor
virtual ~Test() // dtor
public:
void makeHappy();
void makeSad();
void speak();
};
#endif /* TEST_H_ */
this is your Test.cpp file:
It's not advised to use using namespace std;
Don't include your header two times
//.cpp file
#include "Test.h"
#include <iostream>//unresolved inclusion
//ctor
Test::Test() : bhappy_(false)
{}
Test::~Test(){}
void Test::speak() {
if (bhappy_) {//Symbol hapy could not be resolved
std::cout << "Meouw!" << endl;
} else {
std::cout << "Ssssss!" << endl;
}
}
void Test::makeHappy() {
bhappy_ = true;//Symbol hapy could not be resolved
}
void Test::makeSad() { // member decleration not found
bhappy_ = false;//Symbol hapy could not be resolved
}
This is your main function:
#include "Test.h"
int main(int argc, char** argv) {
Test jim;
jim.makeHappy();//method make happy could not be resolved
jim.speak();//method speak could not be resolved
Test bob;
bob.makeSad();//method make happy could not be resolved
bob.speak();//method speak could not be resolved
return 0;
}
You need specify Test::speak().
Take should use this. to use class attribut. Think about getter and setter.
And finally, look C++ training, it should be usefull ^^ .
See you.

inline methods not available as symbols of shared library

If I have a class which will be compiled to a shared object.
The class is declared in a .h file and implemented in a .cpp file.
This class contains a couple of inline methods.
If I write some program that links with this shared library and includes the .h file,
I will get undefined reference errors when linking it.
Is that because there are no symbols exported for inline methods ?
Am I understanding this correctly ?
UPDATE: some example code below
somelib.h
#ifndef __ABC_LIB_H
#define __ABC_LIB_H
#include <iostream>
class ABC {
ABC();
~ABC();
inline void not_callable_outside_library();
void callable_outside_library();
};
#endif
somelib.cpp
#include "somelib.h"
ABC::ABC() {}
ABC::~ABC() {}
void ABC::not_callable_outside_library(){ std::cout<<"not_callable_outside_library"<<std::endl; }
void ABC::callable_outside_library(){ std::cout<<"callable_outside_library"<<std::endl; }
program.cpp
#include "somelib.h"
int main() {
ABC x;
x.not_callable_outside_library();
return 0;
};
Compile somelib.cpp as a shared library( .so object) and link it program.cpp then you get the binary called program.
Now you should get an undefined reference when linking.
Inline functions must be defined in header files. Contrast what you have to the following:
somelib.h:
#ifndef ABC_LIB_H
#define ABC_LIB_H
#include <iostream>
class ABC {
ABC();
~ABC();
void not_callable_outside_library();
void callable_outside_library();
};
inline void ABC::not_callable_outside_library() {
std::cout << "not_callable_outside_library\n";
}
#endif
somelib.cpp:
#include "somelib.h"
ABC::ABC() { }
ABC::~ABC() { }
void ABC::callable_outside_library() {
std::cout << "callable_outside_library\n";
}
program.cpp:
#include "somelib.h"
int main() {
ABC x;
x.not_callable_outside_library();
}

'Undefined reference to Class::method()'

Recently I've been learning how to create methods within classes so that I only have to write a method once and for each of that class I instantiate I can call the one method and it will work only on the variables of the object that called it, I know how to do this when only using main.cpp and no headers however I am confused on how I should be writing this when I use a class header and cpp.
I have a sample of code similar to what I want to achieve:
#include <iostream>
using namespace::std;
class Object
{
public:
int stuff;
void manageStuff();
Object();
};
void Object::manageStuff()
{
stuff++;
}
Object::Object() : stuff(0) {}
Object object1, object2;
int main() {
for (int i = 0; i < 10; i++)
{
object1.manageStuff();
object2.manageStuff();
cout << object1.stuff << "\n";
cout << object2.stuff << "\n";
}
}
This works fine and allows me to have two instances of Object and a method that works independently for each instance, this is my current project:
main.cpp:
#include <iostream>
#include "Test.h"
using namespace std;
int main()
{
Test test;
for (int i = 0; i < 10; i++)
{
test.count(); // Here's my error "undefined reference to Test::count"
}
return 0;
}
Test.cpp
#include <iostream>
#include "Test.h"
using namespace std;
Test::Test()
{
//ctor
}
Test::~Test()
{
//dtor
}
Test.h
#include <iostream>
#ifndef TEST_H
#define TEST_H
class Test
{
public:
Test();
virtual ~Test();
void count();
int counter();
};
#endif // TEST_H
and finally TestFunctions.h
#include <iostream>
#include "Test.h"
#ifndef TESTFUNCTIONS_H_INCLUDED
#define TESTFUNCTIONS_H_INCLUDED
void Test::count()
{
Test::counter++;
std::cout << Test::counter;
}
#endif // TESTFUNCTIONS_H_INCLUDED
I'm sure that there will be something that's very obviously wrong to a more seasoned programmer and I'm about to look a bit thick but any help would be greatly appreciated
Thanks!
I would suggest getting rid of TestFunctions.h, and adding the implementation of Test::count() to Test.cpp. Currently, the TestFunctions.h header is not included anywhere, so you have no access to the definition from main.
You defined (i.e. implemented) Test::count() in a header file (TestFunctions.h), but you never included it anywhere so the code there is not compiled.
You should change it to be in a .cpp file, compile it and link it with the other source files. There's no reason why not to place it in Test.cpp.
Rename TestFunctions.h into TestFunctions.cpp, make it compiled same way as main.cpp and linked.
Alternatively, include TestFunctions.h somewhere, e.g. main.cpp

operator declaration within namespace in a header?

Please excuse me but I didn't know to give a name to the title in a short way.
Why do I need to declare an overloaded operator inside the header to make it work in this example:
HEAD.H
#pragma once
namespace test {
class A {
public:
A() : x(0) {}
int x;
};
A& operator++(A& obj); //this is my question
}
HEAD.CPP
#include "head.h"
namespace test {
A& operator++(A& obj) {
++obj.x;
return obj;
}
}
MAIN.CPP
#include <iostream>
#include "head.h"
using namespace std;
using namespace test;
int main() {
A object;
++object; //this won't work if we delete declaration in a header
return 0;
}
operator++ is defined and declared in a namespace inside "head.cpp" so why do I need to declare it one more time in a header?
Thank you.
The CPP files are compiled independently of each other, and they only see the header files they've included (which are in fact textually added to the source code of the CPP before compilation). As such you'll use the header file to inform the compiler that a function exists with that signature (be it an operator overload).
Then the output from your CPP files is put together by the linker, which is when you'd find out if for instance you had declared a function in a header file but never taken the trouble to implement it.
Simple example with namespaces:
#include <iostream>
namespace test{
int f() { return 42; }
int g() { return -1; }
}
namespace other{
int f() { return 1024; }
}
using namespace other;
int main(){
//error: 'g' was not declared in this scope
//std::cout << g() << std::endl;
std::cout << test::f() << std::endl; //42
std::cout << f() << std::endl; //1024
return 0;
}