Problem Description:
I am working on making a Cart class that has a sf::Sprite(cartSprite) in each instance. However, the static sf::Texture(cartTexture) from which carts are generated is shared between all Cart objects. On construction of a Cart, the sprite is loaded from the texture.
According to the documentation, the sf::Texture has a default constructor that:
Creates an empty texture.
However, when I compile the code below, that declares, but does not define, the sf::Texture, I get linker errors:
/tmp/cclJ5hJp.o: In function `Cart::Cart(sf::Vector2<float> const&, sf::Color, float)':
main.cpp:(.text._ZN4CartC2ERKN2sf7Vector2IfEENS0_5ColorEf[_ZN4CartC5ERKN2sf7Vector2IfEENS0_5ColorEf]+0x46): undefined reference to `Cart::cartTexture'
main.cpp:(.text._ZN4CartC2ERKN2sf7Vector2IfEENS0_5ColorEf[_ZN4CartC5ERKN2sf7Vector2IfEENS0_5ColorEf]+0x87): undefined reference to `Cart::cartTexture'
main.cpp:(.text._ZN4CartC2ERKN2sf7Vector2IfEENS0_5ColorEf[_ZN4CartC5ERKN2sf7Vector2IfEENS0_5ColorEf]+0x9b): undefined reference to `Cart::cartTexture'
main.cpp:(.text._ZN4CartC2ERKN2sf7Vector2IfEENS0_5ColorEf[_ZN4CartC5ERKN2sf7Vector2IfEENS0_5ColorEf]+0xb6): undefined reference to `Cart::cartTexture'
collect2: error: ld returned 1 exit status
Does this mean that I should initialize (define) cartTexture? If so, how do I do that at compile-time when the only constructors for sf::Texture are "copy from another sf::Texture" and the one mentioned above? I can't use a function call to load an image into it, right?
Compile the code with: g++ main.cpp -Wall -Wextra -Werror -std=c++11 -lsfml-graphics -lsfml-window -lsfml-system -o exec
Code:
main.cpp:
#include <SFML/Graphics.hpp>
#include <string>
#include <iostream>
#include <mutex>
class Cart : public sf::Drawable {
public:
// Constructor- create with position, orientation, and color.
Cart(const sf::Vector2f& cartPos_, sf::Color cartColor_, float cartAngle_) {
if (!cartTexture.loadFromFile(textureLoc)) {
std::cout << "File is nonexistent." << std::endl;
} else {
cartTexture.setSmooth(true);
cartTexture.setRepeated(false);
}
cartSprite.setTexture(cartTexture);
cartSprite.setPosition(cartPos_);
cartSprite.setRotation(cartAngle_);
cartSprite.setColor(cartColor_);
}
private:
void draw(sf::RenderTarget& target, sf::RenderStates states) const {
target.draw(cartSprite, states);
return;
}
static sf::Texture cartTexture;
static const std::string textureLoc;
sf::Sprite cartSprite;
};
const std::string Cart::textureLoc = "cart-empty.png";
int main() {
Cart testCart(sf::Vector2f(), sf::Color(200,200,200), 0);
return 0;
}
static class member variables have to be initialized/defined outside of the class definition. You do this for textureLoc but not cartTexture. Before main() add:
sf::Texture Cart::cartTexture;
Related
I couldn't find a proper topic for this question as I haven't got a proper error message.
I'm trying to create a management system for a restaurant which mainly provides pizza as well as other foods(pasta, wings, etc). I want this system to be used by the staff. I have created an abstract class named Foods that can be used to inherit by other foods. So far I have created a class that inherits from Foods named Pizza. Below are my code.
PS: I have used namespaces for organize foods and staff members separately. As far as I know some people doesn't recommend namespace and my apologies if you're one of them.
interfaces.h
#include <vector>
#include <string>
namespace foods{
class Food{
double price;
// since the sauces and drinks are given with foods.
static const std::vector<std::string> sauces;
static const std::vector<std::string> drinks;
public:
virtual int retPrice() = 0;
virtual void ask() = 0; // ask user what to add
virtual ~Food() = default;
};
const std::vector<std::string> Food::sauces = {"Blue cheese", "Garlic", "Honey BBQ", "Marinara"};
const std::vector<std::string> Food::drinks = {"Pepsi", "Mountain Dew", "Coca Cola"};
class Pizza: public Food{
const double price;
const std::string pizzaType; // whether it is chicken, beef, etc.
const std::string size; // small, medium or large
int crust = 1; // how crust it is from 1-5
std::vector<std::string> toppings; // to store toppings
public:
Pizza(): price(15), pizzaType(" "), size(" "){}
int retPrice() override; // the price should change according to the type
void ask() override; // ask the customer for a pizza
void createACustom(); // create a custom pizza with desired toppings
};
};
functions.cpp
#include <iostream>
#include "interfaces.h"
namespace foods{
int Pizza::retPrice(){
return (price+5);
}
void Pizza::ask(){
std::cout << "Hello World!";
}
}
test.cpp
#include "interfaces.h"
int main(){
foods::Pizza* pizza = new foods::Pizza();
}
And I'm getting following error.
/usr/bin/ld: /tmp/ccQRR5B8.o: warning: relocation against `_ZTVN5foods5PizzaE' in read-only section `.text._ZN5foods5PizzaC2Ev[_ZN5foods5PizzaC5Ev]'
/usr/bin/ld: /tmp/ccQRR5B8.o: in function `foods::Pizza::Pizza()':
test.cpp:(.text._ZN5foods5PizzaC2Ev[_ZN5foods5PizzaC5Ev]+0x2b): undefined reference to `vtable for foods::Pizza'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status
I tried using the keyword override and also made a default deconstructor, yet nothing seems working. I want to know what this error message means and a solution for this. In addition to that what is vtable?
Appreciate your time and answers.
EDIT 1
I have compiled it with g++ -Wall -Wextra test.cpp functions.cpp -o test, which is wrong and then I did g++ -Wall -Wextra test.cpp functions.cpp -o test and I'm getting following error.
/usr/bin/ld: /tmp/ccmv2G17.o:(.bss+0x0): multiple definition of `foods::Food::sauces[abi:cxx11]'; /tmp/ccuBNQjX.o:(.bss+0x0): first defined here
/usr/bin/ld: /tmp/ccmv2G17.o:(.bss+0x20): multiple definition of `foods::Food::drinks[abi:cxx11]'; /tmp/ccuBNQjX.o:(.bss+0x20): first defined here
collect2: error: ld returned 1 exit status
Why is it saying that it has multiple definitions?
You need to implement the static member variables sauces and drinks in functions.cpp and not in interfaces.h.
functions.cpp
namespace foods {
int Pizza::retPrice() {
return (price + 5);
}
void Pizza::ask() {
std::cout << "Hello World!";
}
// implement the static variables here.
const std::vector<std::string> Food::sauces = { "Blue cheese", "Garlic", "Honey BBQ", "Marinara" };
const std::vector<std::string> Food::drinks = { "Pepsi", "Mountain Dew", "Coca Cola" };
}
And remove them from interfaces.h.
If you implement them in interfaces.h they end up being implemented in each .cpp file that includes interfaces.h.
It's basically the same problem as if you define a global variable in a .h file.
I am relatively new to c++ and have a solid C and Object Oriented background. So I have the following code written.
I have Person.hpp which is as follows:
class Person
{
private:
struct h
{
char *name;
unsigned char age;
};
struct h entities;
public:
unsigned char age();
char *name();
Person(char *name, unsigned char a);
~Person();
};
The Person.cpp looks as follows:
#include "Person.hpp"
char *Person::name()
{
return entities.name;
}
unsigned char Person::age()
{
return entities.age;
}
Person::Person(char *name, unsigned char a)
{
entities.name = name;
entities.age = a;
}
And finally main.cpp looks like the following:
#include <iostream>
#include "Person.hpp"
int main()
{
Person someone("something", 100);
printf("%s is %d old\n", someone.name(), someone.age());
return 0;
}
I am already aware of the warning that it will cause due to the fact that the string is not constant. This will not cause an error when trying to compile. I tried compiling the code in two different methods. One by just compiling all together which would look like the following:
g++ -o main main.cpp Person.cpp
And the second method I tried was to compile them into object files and then link them together:
g++ -c main.cpp
g++ -c Person.cpp
g++ -o main main.o Person.o
They both give the following error:
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x5b): undefined reference to `Person::~Person()'
/usr/bin/ld: main.cpp:(.text+0x6e): undefined reference to `Person::~Person()'
collect2: error: ld returned 1 exit status
Any help would be greatly appreciated.
You have a destructor declared here in your header file:
public:
unsigned char age();
char *name();
Person(char *name, unsigned char a);
~Person(); // <===== Declared here
But you haven't provided any definitions for it.
However, the destructor is called after your main function returns (you can learn more about this behavior here), so it needs a definition.
You can make the compiler generate the definition for you by either omitting the destructor declaration or use ~Person() = default.
The problem is that you declare both an constructor and destructor in Person.hpp, but only define the constructor in the Person.cpp file.
Try add the following code to Person.cpp:
Person::~Person()
{
}
I'm practicing with gtk (or gtkmm in this case), to which I'm completely new and I'm relatively new to c++. I got a working program that could open a window and put a few widgets in it, but now I'm trying to add an action to a button, and it just won't work.
main.cc:
#include <iostream>
#include "buttons.h"
#include <gtkmm/application.h>
void printLine()
{
std::cout<<"you pressed the button"<<std::endl;
}
int main(int argc, char *argv[])
{
Glib::RefPtr<Gtk::Application> app =
Gtk::Application::create(argc, argv,
"org.gtkmm.examples.base");
Buttons buttons;
return app->run(buttons);
}
buttons.h:
#ifndef GTKMM_EXAMPLE_BUTTONS_H
#define GTKMM_EXAMPLE_BUTTONS_H
#include <gtkmm/window.h>
#include <gtkmm/button.h>
#include <gtkmm/box.h>
class Buttons : public Gtk::Window
{
public:
Buttons();
virtual ~Buttons();
protected:
//Signal handlers:
void on_button_clicked();
//Child widgets:
Gtk::Button m_button;
Gtk::Box buttonBox;
};
#endif //GTKMM_EXAMPLE_BUTTONS_H
buttons.cc:
#include <iostream>
#include "buttons.h"
Buttons::Buttons()
{
m_button.add_pixlabel("info.xpm", "click here");
set_title("Pixmap'd buttons!");
set_border_width(10);
m_button.signal_clicked().connect( sigc::mem_fun(*this,
&Buttons::on_button_clicked) );
add(buttonBox);
buttonBox.pack_start(m_button);
//m_button.show();
show_all_children();
}
Buttons::~Buttons()
{
}
void Buttons::on_button_clicked()
{
printLine();
}
I am using g++ to compile the program and it gives me this error message:
g++ main.cc -o button pkg-config gtkmm-3.0 --cflags --libs
/tmp/ccKyphYe.o: In function main':
main.cc:(.text+0x93): undefined reference toButtons::Buttons()'
main.cc:(.text+0xc5): undefined reference to Buttons::~Buttons()'
main.cc:(.text+0x124): undefined reference toButtons::~Buttons()'
collect2: error: ld returned 1 exit status
You have to put all your source files in the compile line, so just add buttons.cc right after main.cc and you should be good. There are other ways to do it, but just to get you going, that should work.
The longer answer is that the compiler compiles each src file (.cc files in your example) separately and builds object files (.o or .obj). To do this, all it needs are the declarations of the things it uses (#include'd in header files). If they are missing, you get a "compiler error".
But later when it actually puts together the final program that you are going to run, it needs the actual definitions (the actual code) for everything that is used, and if it can't find the actual definition, you get "undefined reference" errors. This is called a "linker error". This means you are missing libraries, archives, or object (.obj) files.
HOWEVER, when you put everything on the same compiler line -- all your c++ src files including one with a main() function, the compiler automatically generates the object files and does the linking all in one step.
So i had the following code which ran perfectly.
Here "rngSource" makes an instance of the class contained in rand.h. rng.rFloat64() calls random numbers between 0 and 1.
main.cpp
#include "rand.h" // rngSource
rngSource rng;
class particle{
public:
double r[nd], v[nd];
particle()
{
for (int i=0; i<nd; ++i)
{
r[i]=L*rng.rFloat64();
v[i]=rng.rFloat64();
}
}
};
But when I tried to separate the class implementation from main.cpp into particle.h and particle.cpp, as indicated below:
particle.h
#ifndef particle_H
#define particle_H
class particle{
public:
double r[2], v[2];
particle();
};
#endif
particle.cpp
#include "rand.h" // rngSource
#include "particle.h"
particle::particle()
{
double ran = (double) rand()/(double)RAND_MAX;
static const double L=10;
for (int i=0; i<2; ++i)
{
r[i]=L*ran;
v[i]=ran;
}
}
While the new main.cpp looks like this:
#include "rand.h" /* rngSource() */
#include "particle.h" /* particle class */
rngSource rng;
int main(){
rng.rseed(getpid()*time(NULL));
particle p[N];
....
}
But when i try to compile i get the following errors:
particle.cpp: In constructor ‘particle::particle()’:
particle.cpp:20:17: error: ‘rng’ was not declared in this scope
r[i]=L*rng.rFloat64(); //ran;
^
particle.o:(.data+0x0): multiple definition of `rng_cooked'
new.o:(.data+0x0): first defined here
particle.o:(.data+0x1300): multiple definition of `kn'
new.o:(.data+0x1300): first defined here
particle.o:(.data+0x1500): multiple definition of `wn'
new.o:(.data+0x1500): first defined here
particle.o:(.data+0x1700): multiple definition of `fn'
new.o:(.data+0x1700): first defined here
new.cpp:(.text+0x1fb1): undefined reference to `rngSource::rseed(long long)'
particle.o: In function `particle::particle()':
particle.cpp:(.text+0x1fa2): undefined reference to `rngSource::rseed(long long)'
particle.cpp:(.text+0x1fb5): undefined reference to `rngSource::rFloat64()'
particle.cpp:(.text+0x1fda): undefined reference to `rngSource::rFloat64()'
collect2: error: ld returned 1 exit status
Would anyone here happen to know how to fix this?
thank you.
Three problems.
Problem 1:
particle.cpp: In constructor ‘particle::particle()’:
particle.cpp:20:17: error: ‘rng’ was not declared in this scope
r[i]=L*rng.rFloat64(); //ran;
The ultra cheesy answer is to add extern rngSource rng; to particle.cpp above the particle constructor. extern means this variable exists, but its storage is allocated elsewhere. The linker will track it down for you. This is quick, dirty, and will get you back on the road with minimal code changes.
Better solutions are to add extern rngSource rng; to rand.h and then define rngSource rng; in rand.cpp for all users or placing extern rngSource rng; in a brand new main.h and include main.h in particle and other modules called by main.
The best solution is probably to create a bool init(rngSource & rng) function in particle and do grunt work the constructor's currently doing. That way if rng doesn't exist, the compiler catches it when you try to call init.
particle p[N];
for (size_t index; index < N; index++)
{
p[index].init(rng);
}
Problem 2
particle.o:(.data+0x0): multiple definition of `rng_cooked'
new.o:(.data+0x0): first defined here
particle.o:(.data+0x1300): multiple definition of `kn'
new.o:(.data+0x1300): first defined here
particle.o:(.data+0x1500): multiple definition of `wn'
new.o:(.data+0x1500): first defined here
particle.o:(.data+0x1700): multiple definition of `fn'
new.o:(.data+0x1700): first defined here
rng_cooked, kn, wn, and fn are almost certainly being defined in rand.h. This means everyone who includes rand.h tries to create their own version of those variables resulting in collisions when the linker tries to line up names with storage locations.
Solution is similar to the first problem: Add extern to the variable definitions in the rand.h and define them in rand.cpp.
Problem 3
new.cpp:(.text+0x1fb1): undefined reference to `rngSource::rseed(long long)'
particle.o: In function `particle::particle()':
particle.cpp:(.text+0x1fa2): undefined reference to `rngSource::rseed(long long)'
particle.cpp:(.text+0x1fb5): undefined reference to `rngSource::rFloat64()'
particle.cpp:(.text+0x1fda): undefined reference to `rngSource::rFloat64()'
No idea. Are you certain you are passing rand.cpp to gcc?
I'm getting some errors when compiling my program. They relate to the constructor and destructor of my class Instruction.
Errors are:
/tmp/ccSWO7VW.o: In function `Instruction::Instruction(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
ale.c:(.text+0x241): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::Instruction(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
ale.c:(.text+0x2ab): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::~Instruction()':
ale.c:(.text+0x315): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::~Instruction()':
ale.c:(.text+0x38d): undefined reference to `vtable for Instruction'
collect2: ld returned 1 exit status
Here is my code:
//classses.h
#include <iostream>
#include <string>
using namespace std;
class Instruction{
protected:
string name;
int value;
public:
Instruction(string _name, int _value);
~Instruction();
void setName(string _name);
void setValue(int _value);
string getName();
int getValue();
virtual void execute();
};
//constructor
Instruction::Instruction(string _name, int _value){
name = _name;
value = _value;
}
//destructor
Instruction::~Instruction(){
name = "";
value = 0;
}
void Instruction::setName(string _name){
name = _name;
}
void Instruction::setValue(int _value){
value = _value;
}
string Instruction::getName(){
return name;
}
int Instruction::getValue(){
return value;
}
/////////////////////////////////////////////////////////////////////
//ale.cpp
#include "headers.h"
#include "functions.h"
#include "classes.h"
#include <list>
using namespace std;
int main(){
return 0;
}
I would guess the problem is due to you declaring a virtual method 'execute' in the Instruction class, and never defining it anywhere. Compilers have to produce a vtable object for a class with virtual methods and really only want one copy of it, so they usually just do it in the compilation unit (source file) that defines the first virtual function...
You did not define your virtual function and/or g++ wants you to make your destructor virtual (because you have virtual functions which assumes inheritance)
Try
virtual void execute()=0;
This will make your class abstract, which seems to be what you intend since execute isn't defined.
If you ever want to use Instruction in more than one .cpp file, you should move the implementation of the class methods into a classes.cpp file.
As people already told, the problem is having execute() that is not implemented. Implement it, or make it pure virtual as says Dan Hook.
Just an extra remark: in many (maybe most depending on what you're coding on) cases, you don't need to implement the destructor. You just need if you want some specific functionnality (flushing data to a file for example).
As long as you have no pointer (as it is the case in your code), you won't have any memory tracking issues. Just remove the destructors: it's safe and it's less code.
However, if only one member is a pointer, then everything gets messy and you have to deal with memory management issues, memory leaks and segfaults ;)