Let's say I have a shared library called libfoo.so that also depends on another shared library called libbar.so. In libfoo.so, the only capability it provides is a class that stores two integers and can return the value of those two integers added together.
libfoo.so:
// Foo.hpp
class Foo
{
int x, y;
public:
Foo(int x, int y);
int add() const;
};
Now, in libbar.so, there are two classes: a Bar1 class that simply stores a string and a Bar2 class that stores an integer that is calculated by creating a Foo object and using the add() function to generate a new integer.
// Bar1.hpp
class Bar1
{
std::string str;
public:
Bar1(const std::string& str);
const std::string& getString() const;
};
// Bar2.hpp
#include "foo.hpp"
class Bar2
{
int z;
public:
Bar2(int x, int y);
int getInt() const;
};
Now, I want to write a program that uses Bar1. I do not care about Bar2. My very simple program looks like this:
// Test.cpp
#include <iostream>
#include "Bar1.hpp"
using namespace std;
int main()
{
Bar1 bar1("Hello");
cout << bar1.getString() << endl;
}
I compile this program like so:
g++ -c test.cpp -o test.o
g++ -o test test.o -lbar
The error that is generated is:
undefined reference to 'Foo::Foo(int, int)'
undefined reference to 'Foo::add() const'
This can be fixed by specifying '-lfoo' to the linker. However, I am now linking in a library that my binary will never use.
Is there a way to clean this up where the compiler understands that my binary does not care about resolving these symbols since I never use Bar2 anywhere in my program?
EDIT:
Adding the implementations of the classes. I didn't think that it mattered. Here they are:
// Foo.cpp
#include "Foo.hpp"
Foo::Foo(int new_x, int new_y)
{
x = new_x;
y = new_y;
}
int Foo::add() const
{
return x + y;
}
And here is Bar1.cpp:
// Bar1.cpp
#include "Bar1.hpp"
Bar1::Bar1(const std::string& the_str)
{
str = the_str;
}
const std::string& Bar1::getString() const
{
return str;
}
And here is Bar2.cpp:
// Bar2.cpp
#include "Bar2.hpp"
Bar2::Bar2(int x, int y)
{
Foo foo(x, y);
z = foo.add();
}
int Bar2::getInt() const
{
return z;
}
Note that it should be obvious that I am writing these classes like this purely for experimentation purposes. I am playing around with the linker and how a developer would link to libraries and use them.
where is foo.cpp and bar.cpp? you didn't implement classes foo and bar:
// foo.cpp
#include "Foo.hpp"
Foo::Foo(int X, int Y) : x(X), y(Y){}
int Foo::add()const{return x + y;}
// Bar1.cpp
#include "bar1.hpp"
Bar1::Bar1(const std::string& STR) : str(STR){}
const std::string& Bar1::getString() const{return str;}
// Bar2.cpp
#include "foo.hpp"
Bar2::Bar2(int X, int Y) : x(X), y(Y) {z = x + y;}
int Bar2::getInt() const{ return z;}
Related
I am trying to use pahole to analyze the memory layout of a C++ program which has some classes inside namespaces. pahole only lists classes in the global namespace. Is there an option to also list the other classes?
MWE:
namespace ns {
class Thing {
public:
int y;
Thing(int y) : y(y) { }
};
};
class Thong {
public:
int z;
Thong(int z) : z(z) { }
};
int main(void) {
ns::Thing x(1);
Thong a(2);
return x.y + a.z;
}
g++ -ggdb3 test.cpp
pahole --version; pahole a.out
v1.10
class Thong {
public:
int z; /* 0 4 */
void Thong(class Thong *, int);
/* size: 4, cachelines: 1, members: 1 */
/* last cacheline: 4 bytes */
};
After poking around in the source, I found out that the --show_private_classes option also prints classes defined in namespaces.
The namespace qualifier is dropped from the class name (ns1::foo and ns2::foo are both printed as just foo) but it's enough for my use case.
(Note that the following is an just example based on real code)
Foo.hpp:
#include <thread.h>
#include <iostream>
#include <string>
class Foo
{
private:
std::thread t;
std::string s;
int x;
int y;
public:
Foo();
Foo(std::string s, int x, int y);
void init();
void init(std::string s, int x, int y);
};
Foo.cpp:
#include "Foo.cpp"
Foo::Foo()
{
this->thread = std::thread(static_cast<void (Foo::*)()>(&Foo::init), this);
}
Foo::Foo(std::string s, int x, int y)
{
this->thread = std::thread(static_cast<void (Foo::*)()>(&Foo::init), this, s, x, y);
}
// Foo::init() and Foo::init(std::string s, int x, int y) definitions
This causes g++ to output quite a lot of errors, the most notable of which is likely
no match for call to '(std::_Bind<std::_Mem_fn<void (Foo::*, std::basic_string<char>, int, int)>) ()' (*upCall)();
^
So what am I doing wrong here?
I am following a tutorial to create a wrapper around C++ code, so that it can be called from C#.
I get an error compiling the wrapper though.
Header.h
class MyClass{
public:
MyClass(int x, int y);
double GetSum();
private:
int x_;
int y_;
};
Below is the source file (body.cpp)
#include "Header.h"
MyClass::MyClass(int x, int y)
{
x = 8;
y = 8;
}
double MyClass::GetSum()
{
int r = x_ + y_;
return r;
}
The wrapper class/dll is as below
#include "C:\Users\tumelo\Documents\Visual Studio 2012\Projects\Emgu\MyClassCpp\MyClassCpp\Header.h"
#include "C:\Users\tumelo\Documents\Visual Studio 2012\Projects\Emgu\MyClassCpp\MyClassCpp\Body.cpp"
//for the function you want made avaible from the dll
extern "C" __declspec(dllexport) double GetResults(int x, int y)
{
//create an instance of the class
MyClass myClass(int x, int y);
return myClass.GetSum();
}
I get an in the wrapper class right at the return statement. The class method does not seem to be recognised for some reason. The error reads:
error C2228: left of '.GetSum' must have class/struct/union
What puzzles me is that this is copy and paste from the tutorial but mine does not work. What could I be missing?
You meant:
MyClass myClass(x, y);
instead of
MyClass myClass(int x, int y);
What you typed is declaring a function named "myClass" that returns a "MyClass" instance and takes two integers. You meant to instantiate a variable named "myClass" of type "MyClass" by by passing it x and y.
I need to have two alternate classes with the same name, that I can switch between each other by simply changing which class is included in main.
For example;
Mode_1.h
class Draw{
private:
// private stuff
public:
void Render(int x, char y);
};
Mode_2.h
class Draw{
private:
// private stuff
public:
void Render(int x, char y);
};
main.cpp
#include "Mode_1.h"
int main(){
Draw D;
int x = 2;
char y = 'x';
D.Render(x, y);
}
Currently I'm having to comment out the .h and .cpp files I'm not using to avoid the "first defined here" error. What I want is that all I have to do to switch between them is change
#include "Mode_1.h"
to
#include "Mode_2.h"
You should put them in different namespaces:
namespace Mode2
{
class Draw{
private:
// private stuff
public:
Draw(int x, char y);
};
}
In main you can then select the namespace you want to use:
#include "Mode_1.h"
#include "Mode_2.h"
using namespace Mode2;
int main()
{
Draw D;
int x = 2;
char y = 'x';
D.Draw(x, y);
return 0;
}
You may try like this:
#ifdef MODE1
#include "Mode_1.h"
#else
#include "Mode_2.h"
#endif
int main(){
Draw D;
int x = 2;
char y = 'x';
Draw(x, y);
}
And compile this source file with -DMODE1 or none depending on you wish to include Mode_1.h or Mode_2.h
I new in C++ and I have difficulty to understand how to get my function with inheritance.
I have a Class that is link to another with inheritance, everything work except:
I cannot reach my superclass function.
Here's my class header : Point.h (I don't include the .cpp):
#ifndef Point_H
#define Point_H
#include <iostream>
class Point{
public:
Point();
void set_values (int , int);
void set_values (int , int , int );
void affichervaleurs();
int getX() const { return x; }
int getY() const { return y; }
private:
int x ;
int y ;
int z ;
};
#endif
Now My other class that try to access the function getX from Point.h :
The header : Carre.h
#ifndef Carre_H
#define Carre_H
#include "Point.h"
class Carre : public Point{
public:
Carre();
//Carre(int a , int b);
//Carre(int a, int b):Point(a,b) {};
//Carre(int a, int b, int c):Point(a, b, c) {};
//const Point &pp;
int Aire (){
};
void affichercar(){
};
};
#endif
Carre.cpp
#include <iostream>
using namespace std;
#include "Carre.h"
#include "Point.h"
Carre::Carre():Point(){
};
//Carre::Carre(int a, int b);
//const &pp;
int Aire (){
return (getX() * getY());
};
void affichercar(){
//cout << "Coordonnees X:" << x << endl;
};
It says that my GetX() is undeclared in my Carre.cpp .
Like I said I'm new in C++
Does someone know what I'm missing to make that code work. ?
Your definition is missing the class scope, which makes it a free function instead of a member.
It should be
int Carre::Aire (){
return getX() * getY();
};
In the .cpp file for Carre, the functions Aire and affichercar are global. Presumably you intended:
int Carre::Aire(){
return (getX() * getY());
};
For example.
Declaring function outside class body requires a class specifier:
int Carre::Aire () {
return (getX() * getY());
};
void Carre::affichercar() {
//...
}
Otherwise
int Aire () {
return (getX() * getY());
};
is just another function in global namespace that can exists simutaneously to Carre::Aire().
This is because you are not implementing the Aire function as being part of the Carre class.
Try changing
int Aire (){
to
int Carre::Aire (){
Also, you already have an implementation of the Aire method in the header file. You should either implement the function inline in the header file, or in the .cpp file, but not both. This also applies to your affichercar method.