I have the following class:
#include <string>
#include <stack>
#include <queue>
#include "map.h"
using namespace std;
#ifndef CONTAINER_H_
#define CONTAINER_H_
struct PathContainer {
int x, y;
string path;
};
class Container {
public:
virtual void AddTile(string, FloorTile *) = 0;
virtual void ClearContainer() = 0;
virtual PathContainer *NextTile() = 0;
};
class StackImpl : public Container {
private:
stack<PathContainer> cntr;
public:
StackImpl();
void AddTile(string, NeighborTile *);
void ClearContainer();
PathContainer *NextTile();
};
class QueueImpl : public Container {
private:
queue<PathContainer> cntr;
public:
QueueImpl();
void AddTile(string, NeighborTile *);
void ClearContainer();
PathContainer *NextTile();
};
#endif
When I try creating StackImpl or QueueImpl object like so:
Container *cntr;
cntr = new StackImpl();
or
Container *cntr;
cntr = new QueueImpl();
I get the following error at compile:
escape.cpp: In function ‘int main(int, char**)’:
escape.cpp:26: error: cannot allocate an object of abstract type ‘StackImpl’
container.h:23: note: because the following virtual functions are pure within ‘StackImpl’:
container.h:18: note: virtual void Container::AddTile(std::string, FloorTile*)
Any ideas?
typeid(NeighborTile *) != typeid(FloorTile *). The signatures differ, so they don't count as "the same" method even if NeighborTile inherits from FloorTile.
Related
I'm trying to pass a type as a argument to a method that will properly construct and push a object to a vector of unique_ptr, however the created object is always the Base object. This happens when using emplace_back(), the same works fine if I just instantiate the object.
Constructing the object outside the vector works fine, however I'm not sure how to move the pointer to the vector after.
body_parts.hpp
#include <vector>
#include <string>
#include <fmt/core.h>
using namespace std;
namespace uhcr {
class body_part
{
public:
string name = "Generic";
template <class T>
void add_body_part()
{
this->body_parts.emplace_back<T*>(new T());
fmt::print("{}\n", this->body_parts.back()->name);
}
private:
vector<unique_ptr<body_part>> body_parts;
};
class torso : public body_part
{
public:
string name = "Torso";
};
}
character.hpp
#include <string>
#include "components/body_parts.hpp"
using namespace std;
namespace uhcr {
class character : public body_part
{
public:
string name = "Character";
};
}
main.cpp
#define FMT_HEADER_ONLY
#include <memory>
#include <fmt/core.h>
#include "src/character.hpp"
using namespace fmt;
using namespace uhcr;
void create_human() {
character human;
human.add_body_part<torso>();
}
int main(void) {
create_human();
return 1;
}
The error is at add_body_part(), when running this code it prints "Generic".
You have multiple data members named name in your subclasses. You probably want to assign values to the member in body_part, not declare new members that shadow it.
class body_part
{
public:
body_part() = default;
string name = "Generic";
template <class T>
void add_body_part()
{
this->body_parts.emplace_back<T*>(new T());
fmt::print("{}\n", this->body_parts.back()->name);
}
protected:
body_part(std::string name) : name(name) {}
private:
vector<unique_ptr<body_part>> body_parts;
};
class torso : public body_part
{
public:
torso() : body_part("Torso") {}
};
class character : public body_part
{
public:
character() : body_part("Character") {}
};
There is no slicing in your code. You seem to expect virtual member variables, but there is no such thing. You get expected output when you use virtual methods:
#include <memory>
#include <vector>
#include <iostream>
#include <string>
using namespace std;
class body_part
{
public:
virtual std::string getName() { return "Generic";}
template <class T>
void add_body_part()
{
this->body_parts.emplace_back<T*>(new T());
std::cout << this->body_parts.back()->getName();
}
virtual ~body_part() = default;
private:
vector<unique_ptr<body_part>> body_parts;
};
class torso : public body_part
{
public:
std::string getName() override { return "Torso"; }
};
class character : public body_part
{
public:
std::string getName() override { return "Character"; }
};
void create_human() {
character human;
human.add_body_part<torso>();
}
int main(void) {
create_human();
return 1;
}
Live Demo
This is a much simpler example of the same effect:
#include <iostream>
#include <string>
struct foo {
std::string name = "Generic";
void x(foo& f){
std::cout << f.name;
}
virtual ~foo() = default;
};
struct bar : foo {
std::string name = "Beneric";
};
int main () {
foo f;
bar b;
f.x(b);
}
bar has two name members. In foo when you write std::cout << f.name it refers to foo::name not to bar::name. You can access bar::name also in foo provided the foo is acutally a bar, but that would lead to some backwards design:
#include <iostream>
#include <string>
struct foo {
std::string name = "Generic";
void x(foo& f);
virtual ~foo() = default;
};
struct bar : foo {
std::string name = "Beneric";
};
void foo::x(foo& f) {
std::cout << dynamic_cast<bar&>(f).name;
}
int main () {
foo f;
bar b;
f.x(b);
}
In your example the dynamic_cast would be less of an issue, as you just created a T and you know it is a T, but nevertheless you should use virtual methods rather than relying on casts.
I have following C++ code
Configuration.h
#include <cstdint>
typedef struct
{
uint8_t id;
uint32_t data;
} Config;
Handler.h
class HandlerBase
{
public:
typedef void (*func_ptr)(void *data);
HandlerBase(func_ptr function) : function(function) {}
private:
func_ptr function;
};
template<class T>
class Handler : public HandlerBase
{
public:
Handler() : HandlerBase(&fun_01) {}
private:
static void fun_01(void *data) {}
};
AbstractBase.h
class AbstractBase
{
public:
virtual void method_01() = 0;
virtual void method_02() = 0;
};
A.h
#include "AbstractBase.h"
#include "Handler.h"
#include "Configuration.h"
class A : public Handler<A>, public AbstractBase
{
public:
A();
void method_01();
void method_02();
private:
Config cfg;
};
A.cpp
#include "A.h"
A::A() {}
void A::method_01() {}
void A::method_02() {}
main.cpp
int main(int argc, char** argv) {
A a;
return 0;
}
In case I have steped through the code in the debugger I have noticed that whenever I create the a instance of the A class in the main the a instance contains two instances of the cfg struct. Here is the output of my debugger (I have been using the GDB along with the g++ compiler (v 4.6.3) under Netbeans IDE v8.2. under Windows 10 Pro)
EDIT_01:
I have found that I can store values only into one of the cfg instances. After assignment into the struct items
cfg.id = 0x55;
cfg.data = 0xAAAAAAAA;
I can see follwing content of the cfg structs
In case I observe the content of the memory at address 0xffffcbd0 (content of the this pointer) I see following (one byte of id item with three padding bytes followed by four bytes of the data item)
EDIT_02:
I have added below given method into the A class
void A::init()
{
cfg.id = 0x55;
cfg.data = 0xAAAAAAAA;
}
and modified the method_01 in following manner
void A::method_01()
{
if ((cfg.data == 0xAAAAAAAA) && (cfg.id == 0x55)) {
std::cout << "Config ok!" << std::endl;
}
}
The main.cpp
int main(int argc, char** argv) {
A a;
a.init();
a.method_01();
return 0;
}
prints the Config ok! message.
At the same time only one instance of cfg struct is created in case the A class inherits only from the Handler. Please can anybody tell me what is the reason for this behavior? Is there any way how to avoid this duplication of the class member? Thanks in advance.
You see I've been trying to create a std::vector which contains the Entity class inside the IState class. Both classes are interfaces.
The error is
'Entity' was not declared in this scope
and it points to :
protected:
std::vector <Entity*> ent_map;
inside IState.h
I've been trying for hours now to solve it. Once I made a forward declaration inside IState.h but once I did and tried to use the vector it spews out that it's an incomplete class, so I was back to square one.
Any ideas?
Entity.h
#ifdef __ENTITY__
#define __ENTITY__
#include <iostream>
#include <SDL.h>
class Entity
{
public:
virtual ~Entity();
virtual void load(const char* fileName, std::string id, SDL_Renderer* pRenderer) = 0;
virtual void draw() = 0;
virtual void update() = 0 ;
virtual void clean() = 0;
/*void int getX() { return m_x;}
void int getY() { return m_y;}
void std::string getTexID {return textureID;}
*/
};
#endif // __ENTITY__
IState.h
#ifndef IState_
#define IState_
#include "Entity.h"
#include <vector>
class IState
{
public :
virtual ~IState();
virtual void update() = 0;
virtual void render(SDL_Renderer* renderTarget) = 0;
virtual bool onEnter() = 0;
virtual bool onExit() = 0;
virtual void handleEvents(bool* gameLoop,SDL_Event event) = 0;
virtual void resume() = 0;
virtual std::string getStateID() = 0;
virtual void setStateID(std::string id) = 0;
protected:
std::vector <Entity*> ent_map;
};
#endif // IState_
The content of "Entity.h" won't be included at all.
Change
#ifdef __ENTITY__
to
#ifndef __ENTITY__
BTW: The name contains double underscore or begins with an underscore followed by an uppercase letter is reserved in C++, you need to be careful about it.
I have three classes defined in header files:
Organizm.h:
#ifndef Organizm_H
#define Organizm_H
class Organizm {
public:
int sila;
int inicjatywa;
int trup;
virtual void akcja() = 0;
virtual void kolizja() = 0;
virtual void rysowanie() = 0;
};
#endif
Zwierze.h:
#include "config.h"
#include "Organizm.h"
#ifndef Zwierze_H
#define Zwierze_H
class Zwierze : public Organizm {
public:
void akcja(int *, int *);
void kolizja(Organizm *);
};
#endif
And Wilk.h:
#include "Zwierze.h"
#ifndef Wilk_H
#define Wilk_H
class Wilk: public Zwierze {
public:
Wilk();
void rysowanie();
};
#endif
All non virtual methodths are defined in corresponding files: Organizm.cpp, Zwierze.cpp Wilk.cpp
But when compiling I get following error messg:
g++ -c -o main.o main.cpp
main.cpp: In function ‘int main()’:
main.cpp:13:16: error: cannot allocate an object of abstract type ‘Wilk’
w1 = new Wilk();
^
In file included from main.cpp:5:0:
Wilk.h:6:7: note: because the following virtual functions are pure within ‘Wilk’:
class Wilk: public Zwierze {
^
In file included from Swiat.h:2:0,
from main.cpp:3:
Organizm.h:11:16: note: virtual void Organizm::akcja()
virtual void akcja() = 0;
^
Organizm.h:12:16: note: virtual void Organizm::kolizja()
virtual void kolizja() = 0;
^
<wbudowane>: polecenia dla obiektu 'main.o' nie powiodły się
make: *** [main.o] Błąd 1
zsh: exit 2 make
What am I doing wrong and how can I solve that?
void akcja(int *, int *) are different from void akcja() (overloading). You don't define void akcja() anywhere.
In Zwierze You are not overriding the methods from Organizm.
This compiles:
#include <iostream>
using namespace std;
class Organizm {
public:
int sila;
int inicjatywa;
int trup;
virtual void akcja() = 0;
virtual void kolizja() = 0;
virtual void rysowanie() = 0;
};
class Zwierze : public Organizm {
public:
void akcja(){};
void kolizja(){};
};
class Wilk: public Zwierze {
public:
Wilk(){};
void rysowanie(){};
};
int main() {
Wilk wilk;
return 0;
}
In your case already Zwierze has 2 sets of akcja and kolizja declared. One declared AND defined in Organizm and its implementation. The second and were derived from Organizm and NOT overridden due to different signatures. What you did was overloading.
you didnt declare void rysowanie() in any of your class, therefore your Wilk class remains a abstract class. and a abstract class cant be instantiated.
Moreover, you have overloaded the virtual functions void akcja() and void kolizja(), which is again different and dont make your class an non abstract class.
define the below functions in Organizm
virtual void akcja(int *, int *);
virtual void kolizja(Organizm *);
and also give body of void rysowanie()
I have a very simple base class/ derived class scenario:
#include <tchar.h>
#include <stdio.h>
#include <iostream.h>
#include <conio.h>
class BaseChannel{
private:
public:
virtual ~BaseChannel(){};
virtual void SayBoo( bool SelectAll)=0;
};
class gdbChannel: BaseChannel{
public:
void SayBoo(bool SelectAll) {if (SelectAll) cout<<"boo";}
};
class UsesChannel{
public:
BaseChannel * c;
};
int _tmain(int argc, _TCHAR* argv[])
{
gdbChannel gc;
UsesChannel uc;
// uc.c = &gc; //cannot convert gdbChannel* to BaseChannel*
uc.c = (BaseChannel*)&gc; // works
uc.c->SayBoo(true);
getch();
return 0;
}
My initial implementation, commented out above, will not compile. Can anyone explain why? I feel that since gdbChannel is explicitly an instance of BaseChannel the cast shouldn't be necessary.
That is because gdbChannel does not use public inheritance to derive from BaseChannel (the default for class types is private).
If public inheritance is what you wanted to express, just write:
class gdbChannel : public BaseChannel{
// ^^^^^^
public:
void SayBoo(bool SelectAll) {if (SelectAll) cout<<"boo";}
};