I have a base class sprite:
sprite.hh
#include <iostream>
#include "vector.hh"
#ifndef SPRITE
#define SPRITE
class sprite
{
private:
vector pos;
//the width and height of the sprite
vector dimensions;
int imArrIndex;
public:
sprite();
sprite(vector p, vector d, int i);
void setPos(vector v);
vector getPos();
void setDimensions(vector v);
vector getDimensions();
void setImArrIndex(int i);
int getImArrIndex();
void movePos(vector v);
};
#endif
sprite.cc:
#include <iostream>
#include "sprite.hh"
#include "vector.hh"
using namespace std;
sprite::sprite()
{
cout << "sprite created\n";
}
sprite::sprite(vector p, vector d, int i)
{
pos = p;
dimensions = d;
imArrIndex = i;
}
void sprite::setPos(vector v)
{
pos = v;
}
vector sprite::getPos()
{
return pos;
}
void sprite::setDimensions(vector v)
{
dimensions = v;
}
vector sprite::getDimensions()
{
return dimensions;
}
void sprite::setImArrIndex(int i)
{
imArrIndex = i;
}
int sprite::getImArrIndex()
{
return imArrIndex;
}
void sprite::movePos(vector v)
{
pos.setX(pos.getX() + v.getX());
pos.setY(pos.getY() + v.getY());
}
and a derived class actor:
actor.hh:
#include <iostream>
#include "sprite.hh"
#include "vector.hh"
#ifndef ACTOR
#define ACTOR
class actor : public sprite
{
private:
public:
actor(vector p, vector d, int i) : sprite(p, d, i);
};
#endif
actor.cc:
#include <iostream>
#include "sprite.hh"
#include "actor.hh"
#include "vector.hh"
using namespace std;
actor::actor(vector p, vector d, int i) : sprite(p, d, i)
{
cout << "actor created\n";
}
Both classes use the vector class:
vector.hh:
#include <iostream>
#include <cmath>
#ifndef VECTOR
#define VECTOR
class vector
{
private:
int x;
int y;
public:
vector();
vector(int px, int py);
void setX(int px);
int getX();
void setY(int py);
int getY();
//get the pixel distance between this vector and a given vector
int getDistance(vector v);
};
#endif
vector.cc:
#include <iostream>
#include "vector.hh"
using namespace std;
vector::vector()
{
cout << "vector created\n";
}
vector::vector(int px, int py)
{
x = px;
y = py;
cout << "vector created\n";
}
void vector::setX(int px)
{
x = px;
}
int vector::getX()
{
return x;
}
void vector::setY(int py)
{
y = py;
}
int vector::getY()
{
return y;
}
//get the pixel distance between this vector and a given vector
int vector::getDistance(vector v)
{
return sqrt( pow(x - v.getX(), 2) + pow(y - v.getY(), 2) );
}
Right now I am just trying to get the constructor for the actor working in my main code with this section:
vector p(0,0);
vector d(0,0);
actor a(p, d, 1);
But I am getting this error when running my makefile:
g++ -c level.cc
In file included from level.cc:6:
actor.hh: In constructor ‘actor::actor(vector, vector, int)’:
actor.hh:15:53: error: expected ‘{’ at end of input
actor(vector p, vector d, int i) : sprite( p, d, i);
^
make: *** [makefile:11: level.o] Error 1
My makefile works just fine if I don't call the base constructor in the derived class so I'm sure its not an error in my makefile, but here is my makefile just in case:
FrogGame: frogmain.o game.o level.o sprite.o actor.o vector.o
g++ -std=c++0x -Wall -pedantic -o FrogGame frogmain.o game.o level.o sprite.o actor.o vector.o `sdl2-config --cflags --libs` -lSDL2_image
frogmain.o: frogmain.cc game.hh level.hh sprite.hh vector.hh
g++ -c frogmain.cc
game.o: game.cc level.hh sprite.hh actor.hh vector.hh
g++ -c game.cc
level.o: level.cc sprite.hh actor.hh vector.hh
g++ -c level.cc
actor.o: actor.cc vector.hh
g++ -c actor.cc
sprite.o: sprite.cc vector.hh
g++ -c sprite.cc
vector.o: vector.cc
g++ -c vector.cc
I'm assuming I have some syntax wrong in the constructor but can't seem to fix it, any suggestions?
In your header file, you have this line:
public:
actor(vector p, vector d, int i) : sprite(p, d, i); // Error!
I see what you're trying to do here, but this isn't legal C++ syntax. If you plan to declare the actor constructor but then define it in a .cpp file, which is what you're doing here, just write
actor(vector p, vector d, int i);
Then, in the .cpp file, as you've done, write
actor::actor(vector p, vector d, int i) : sprite(p, d, i)
{
cout << "actor created\n";
}
As you have it written right now, the C++ compiler sees the declaration of the actor constructor. When it then sees the initialization list (the : sprite(p, d, i) part), it thinks "oh, okay, you're defining the functions here." It's then mightily confused about why there's a semicolon instead of the actual body of the function, which is what the compiler error you're getting says.
Related
Template class :
#ifndef ARRAYC_H
#define ARRAYC_H
#include <iostream>
using namespace std;
template <class T>
class Array
{
private:
T* m_ptr;
int m_size;
public:
Array();
Array(int size);
~Array();
int size() const;
bool is_Empty() const;
T& operator[](int index);
};
#endif
and class declaration Header..
#ifndef ARRAY_H
#define ARRAY_H
#include "ArrayC.h"
using namespace std;
template <class T>
Array<T>::Array(int size) {
if(size!=0) {
T* m_ptr = new T[size]{};
m_size = size;
}
}
template <class T>
Array<T>::~Array() {
cout <<"Deleted" << endl;
delete [] m_ptr;
}
template <class T>
int Array<T>::size() const {
return m_size;
}
template <class T>
bool Array<T>::is_Empty() const {
return (m_size==0);
}
template <class T>
T& Array<T>::operator[](int index) {
if(index< m_size) {
return m_ptr[index];
}
else {
cout <<"Index Specifed is out of Range" << endl;
exit(0);
}
}
#endif
program
#include "Array.h"
#include <iostream>
using namespace std;
int main() {
Array<int> A(2);
A[0] = 1;
A[1] = 2;
cout << A[0] << endl;
cout << A[1] << endl;
}
it compiles and also outputs value but
then it stops and then makefile shows error.
g++ -g -std=c++17 -c -o Main.o Main.cpp
g++ -g -std=c++17 -o Execute Main.o
Execute
1
2
Deleted
Makefile:13: recipe for target 'run' failed
mingw32-make: *** [run] Error -1073741819
after deleted is printed it stops for some time and then shows error.
run target only has one recipe that is to execute the program Execute.exe.
Really sorry for this type of description
but its doesnt show any type of error.
CCX_FLAGS = g++ -g -std=c++17
CCX_OF = -o
CCX_CF = -c
.PHONY : all preExwork Obclean Exclean
all : preExwork run Obclean
preExwork :
$(CCX_FLAGS) $(CCX_CF) $(CCX_OF) Main.o Main.cpp
$(CCX_FLAGS) $(CCX_OF) Execute Main.o
run :
Execute
Obclean :
del /f Main.o
Exclean :
del /f Execute.exe
I am learning C++ and I have a Class declaration in a .h file, and the definitions on a .cpp file. The .h file is as follows:
// matrix.h
class Matrix {
private:
int r; // number of rows
int c; // number of columns
double* d;
public:
Matrix(int nrows, int ncols, double ini = 0.0); // declaration of the constructor
~Matrix(); // declaration of the destructor
inline double operator()(int i, int j) const;
inline double& operator()(int i, int j);
};
And the .cpp is:
// matrix.cpp
#include "matrix.h"
Matrix::Matrix(int nrows, int ncols, double ini) {
r = nrows;
c = ncols;
d = new double[nrows*ncols];
for (int i = 0; i < nrows*ncols; i++) d[i] = ini;
}
Matrix::~Matrix() {
delete[] d;
}
inline double Matrix::operator()(int i, int j) const {
return d[i*c+j];
}
inline double& Matrix::operator()(int i, int j) {
return d[i*c+j];
}
And the test file is:
// test.cpp
#include <iostream>
#include "matrix.h"
using namespace std;
int main(int argc, char *argv[]) {
Matrix neo(2,2,1.0);
cout << (neo(0,0) = 2.34) << endl;
return EXIT_SUCCESS;
}
Problem: when I compile the test.cpp file using g++ test.cpp, or using g++ test.cpp matrix.cpp, I get the errors: warning: inline function 'Matrix::operator()' is not defined and ld: symbol(s) not found for architecture x86_64.
Question: What is failing? How can I understand what is happening? Thanks for helping!
The body of an inline function should be visible at all callsites of the function.
In your setup you need to move those two inline definitions from matrix.cpp to matrix.h ; or make them non-inline.
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;}
Here is a mini-example of my code, how to correctly initialize member pool_ in the constructor.
#include <vector>
#include <thread>
#include <iostream>
namespace b {
class A;
typedef void (A::*Func) (void);
struct c {
Func fun;
int num;
std::vector<std::thread> threads;
};
class A {
public:
A() {
pool_ = {{&A::func1, 1, }, {&A::func2, 2, }}; // how to initialize?
}
private:
std::vector<c> pool_;
void func1(void) { std::cout << "func1\n"; };
void func2(void) { std::cout << "func2\n"; };
void CreateThread(c& pool) {
for (int i = 0; i < pool.num; ++i) {
pool.threads.push_back(std::thread(pool.fun, this));
}
}
};
} // namespace b
int main() {
b::A a;
return 0;
}
Platform: Ubuntu 14.04 with g++ 4.8.4
compile command:
g++ -Wall -std=c++11 test.cc -lpthread -o test
The major error message is:
error: use of deleted function ‘std::thread::thread(std::thread&)’
I know it is because copy construction and assignment of std::thread is not allowed. But I tried other ways and failed.
Two steps to solving this elegantly:
provide a constructor for c that does 'the right thing'
struct c {
c(Func fun, int num, std::vector<std::thread> threads = {})
: fun(fun)
, num(num)
, threads(std::move(threads))
{}
Func fun;
int num;
std::vector<std::thread> threads;
};
Then neatly emplace your objects into pool_
A()
{
pool_.emplace_back(&A::func1, 1);
pool_.emplace_back(&A::func2, 2);
}
... and save it into self-defined object type? I'm using PostgreSQL. When I have everything in one file, it works. But I wanted to split this into class-files like you always do when writing in cpp. When I divided my code into *.h and *.cpp files, I'm getting errors.
Here are my files:
test.h
class MyInt
{
public:
MyInt();
MyInt(int i);
void set(int i);
int get() const;
private:
int i_;
};
test.cpp
#include "test.h"
#include <soci.h>
#include <postgresql/soci-postgresql.h>
MyInt::MyInt()
{
}
MyInt::MyInt(int i)
{
this->i_ = i;
}
int MyInt::get() const
{
return this->i_;
}
void MyInt::set(int i)
{
this->i_ - i;
}
namespace soci
{
template <>
struct type_conversion<MyInt>
{
typedef int base_type;
static void from_base(int i, soci::indicator ind, MyInt & mi)
{
if (ind == soci::i_null)
{
throw soci_error("Null value not allowed for this type");
}
mi.set(i);
}
static void to_base(const MyInt & mi, int & i, soci::indicator & ind)
{
i = mi.get();
ind = soci::i_ok;
}
};
}
main.cpp
#include <iostream>
#include "test.h"
int main(int argc, char **argv)
{
MyInt i;
sql.open(soci::postgresql, "dbname=mydb user=postgres password=postgrespass");
sql << "SELECT count(*) FROM person;", soci::into(i);
std::cout << "We have " << i.get() << " persons in the database.\n";
sql.close();
return 0;
}
I compile it like this:
g++ main_test.cpp test.h test.cpp -o App -lsoci_core -lsoci_postgresql
-ldl -lpq -I /usr/local/include/soci -I /usr/include/postgresql
and got those errors:
In file included from /usr/local/include/soci/into-type.h:13:0,
from /usr/local/include/soci/blob-exchange.h:12,
from /usr/local/include/soci/soci.h:18,
from main_test.cpp:3:
/usr/local/include/soci/exchange-traits.h: In instantiation of â€soci::details::exchange_traits<MyInt>’:
/usr/local/include/soci/into.h:29:60: instantiated from â€soci::details::into_type_ptr soci::into(T&) [with T = MyInt, soci::details::into_type_ptr = soci::details::type_ptr<soci::details::into_type_base>]’
main_test.cpp:29:59: instantiated from here
/usr/local/include/soci/exchange-traits.h:35:5: error: incomplete type â€soci::details::exchange_traits<MyInt>’ used in nested name specifier
THE ABOVE PROBLEM IS SOLVED, TAKE A LOOK AT #JohnBandela ANSWER.
The code where you specialize type_conversion
template<>
struct type_conversion<MyInt>
Needs to be in test.h not test.cpp. The problem is if you have it in test.cpp like you do now, it is not visible in main.cpp where you are using SOCI