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()
Related
Context: I'm developing a communications protocol for an embedded application.
The protocol basically needs to be a wrapper allowing it to be ported to different communications methods (Serial, WiFi, Bluetooth, etc) and be able to support communication with and control of different peripherals (DAC, accelerometer, etc).
The idea is that each communications method (A_base in my example) would have its own implementation while having the same external functions, such that the code for the peripherals would not need to be rewritten if (for example) we moved from bytes-over-serial to json-over-wifi.
Each peripheral implements a derivative of a base class (B_base in my example) to handle the transmission of data specific to that peripheral, hence each B must be able to call functions from derivatives of A_base without necessarily knowing which derivative has been used.
When I compile code which is written in the same way as the following, I get errors such as:
derivedB.cpp: In member function 'virtual void derivedB::setupData()':
derivedB.cpp:xx: error: no matching function for call to 'A_base::callFromB(const char*, int&)'then
baseClasses.h:xx:yy: note: candidate: virtual void A_base::callFromB()
virtual void callFromB() =0;
candidate expects 0 arguments, 2 provided
Have I implemented the functionality I described wrong, or is it simply not possible, or does it require a specific version of C++?
I'm not an experienced C++ programmer, so any help would be greatly appreciated.
Example code:
BASE CLASSES
/* ==== baseClasses.h ==== */
#ifndef BASECLASSES_H
#define BASECLASSES_H
#include <list>
// forward declarations
class A_base;
class B_base;
class A_base {
protected:
std::list<B_base*> listOfBs;
public:
A_base();
void addB(B_base*);
virtual void callFromB() =0;
virtual void alsoCallFromB(short*, int) =0;
virtual void alsoCallFromB(int*, int) =0;
virtual void alsoCallFromB(float*, int) =0; // overloaded
};
class B_base {
protected:
int someCommonInt;
A_base* A;
public:
B_base(int, A_base&);
virtual void setupData() =0;
};
#endif
/* ==== baseClasses.cpp ==== */
#include "baseClasses.h"
A_base::A_base() {}
void A_base::addB(B_base* b { listOfBs.push_back(b); }
B_base::B_base(int i, A_base& ref_A) {
someCommonInt = i;
A = &ref_A;
A->addB(this);
}
DERIVATIVE OF A
/* ==== A_derived.h ==== */
#include "baseClasses.h"
class derivedA : public A_base {
public:
virtual void callFromB(const char*, int);
virtual void alsoCallFromB(short*, int);
virtual void alsoCallFromB(int*, int);
virtual void alsoCallFromB(float*, int); // overloaded
};
/* ==== A_derived.cpp ==== */
#include "A_derived.h"
void derivedA::callFromB(const char* msg, int foo) {
// do something with msg and foo
}
void derivedA::alsoCallFromB(short* data, int len=1) { // overloaded derived function with default value
// do something with short int data
}
void derivedA::alsoCallFromB(int* data, int len=1) { // overloaded derived function with default value
// do something with int data
}
void derivedA::alsoCallFromB(float* data, int len=1) { // overloaded derived function with default value
// do something with float data
}
DERIVATIVE OF B
/* ==== B_derived.h ==== */
#include "baseClasses.h"
class derivedB : public B_base {
private:
int* intData;
float* floatData;
int arraySize;
public:
virtual void setupData(int*, float*, int);
void callAWithDataArrays();
void callAWithSingleValue(int);
};
/* ==== B_derived.cpp ==== */
#include "B_derived.h"
void derivedB::setupData(int* iPtr, float* fPtr, int size) {
intData = iPtr;
floatData = fPtr;
arraySize = size;
A->callFromB("B setup done.\n", 0);
}
void derivedB::callAWithDataArrays() {
A->alsoCallFromB(intData, arraySize);
A->alsoCallFromB(floatData, arraySize);
}
void derivedB::callAWithSingleValue(int idx) {
A->alsoCallFromB(intData[idx]);
A->alsoCallFromB(floatData[idx]);
}
MAIN PROGRAM
#include "A_derived.h"
#include "B_derived.h"
int main(int argc, char** argv) {
int myInts[] = new int[8];
float myFloats[] = new float[8];
float anotherFloat = 1.23;
A_derived myA;
B_derived myB(1337, (A_base&)myA);
myB.setupData(myInts, myFloats, 8);
myB.callAWithDataArrays();
myB.callAWithSingleValue(4);
return 0;
}
You have a pure virtual function virtual void callFromB() =0; that is not being overridden in the derived class ie:
virtual void callFromB(const char*, int); != virtual void callFromB()
You can change A_base::callFromB() to A_base::callFromB(const char*, int)
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 defined an interface class A which defines some basic functions. In my implementation I have a base class A0 which implements this interface and from this base class I have derived several other classes in a hierarchy.
#include <iostream>
#include <string>
class IContainer
{
public:
IContainer() {};
virtual ~IContainer() {};
virtual void loadDefaults() = 0;
virtual void storeDefaults() = 0;
virtual bool open() = 0;
virtual bool close() = 0;
};
class IContainerReader
{
public:
IContainerReader() {};
virtual ~IContainerReader() {};
virtual bool read() = 0;
};
class IContainerWriter
{
public:
IContainerWriter() {};
virtual ~IContainerWriter() {};
virtual bool write() = 0;
};
class ContainerBase : public IContainer
{
public:
ContainerBase() {}
virtual ~ContainerBase() {}
void loadDefaults() {}
void storeDefaults() {}
};
class CSVBase : public ContainerBase
{
public:
CSVBase() {}
virtual ~CSVBase() {}
void setFilename() {}
bool open() { return true; }
bool close() { return true; }
};
class CSVReader : public CSVBase, public IContainerReader
{
public:
CSVReader() {}
virtual ~CSVReader() {}
bool read() { return true; }
};
class CSVWriter : public CSVBase, public IContainerWriter
{
public:
CSVWriter() {}
virtual ~CSVWriter() {}
bool write() { return true; }
};
int main(int argc, char *argv[])
{
CSVReader r;
CSVWriter w;
IContainerReader *ir = &r;
IContainerWriter *iw = &w;
ir->open();
iw->open();
ir->read();
iw->write();
ir->close();
iw->close();
return 0;
}
As you can see I defined a IContainerReader and a IContainerWriter class which defines special functions only relevant to the respective implementation.
But now I have a problem, because I want to be sure that a Reader or a writer always has the container base as well. So the logical solution would be to derive IContainerReader/-Writer from IContainer. But when I do this, thge compiler complains, because it expects that now a Reader/Writer object implements again the base functions as well, which are already defined via the base class. But if I let IContainerReader not derive from IContainer a pointer to one of those objects is not guruanteed to have the IContainer functionality as well.
If I try to compile it like this I get errors, because IContainerReader is not a IContainer
||=== Build: Debug in CPPMingW (compiler: GNU GCC Compiler) ===|
D:\src\c\Tests\CPPMingW\main.cpp||In function 'int main(int, char**)':|
D:\src\c\Tests\CPPMingW\main.cpp|83|error: 'class IContainerReader' has no member named 'open'|
D:\src\c\Tests\CPPMingW\main.cpp|84|error: 'class IContainerWriter' has no member named 'open'|
D:\src\c\Tests\CPPMingW\main.cpp|89|error: 'class IContainerReader' has no member named 'close'|
D:\src\c\Tests\CPPMingW\main.cpp|90|error: 'class IContainerWriter' has no member named 'close'|
||=== Build failed: 4 error(s), 0 warning(s) (0 minute(s), 5 second(s)) ===|
However, if I derive IContainerReader from IContainer as it should be, I get the following errors:
||=== Build: Debug in CPPMingW (compiler: GNU GCC Compiler) ===|
D:\src\c\Tests\CPPMingW\main.cpp||In function 'int main(int, char**)':|
D:\src\c\Tests\CPPMingW\main.cpp|78|error: cannot declare variable 'r' to be of abstract type 'CSVReader'|
D:\src\c\Tests\CPPMingW\main.cpp|58|note: because the following virtual functions are pure within 'CSVReader':|
D:\src\c\Tests\CPPMingW\main.cpp|11|note: virtual void IContainer::loadDefaults()|
D:\src\c\Tests\CPPMingW\main.cpp|12|note: virtual void IContainer::storeDefaults()|
D:\src\c\Tests\CPPMingW\main.cpp|14|note: virtual bool IContainer::open()|
D:\src\c\Tests\CPPMingW\main.cpp|15|note: virtual bool IContainer::close()|
D:\src\c\Tests\CPPMingW\main.cpp|79|error: cannot declare variable 'w' to be of abstract type 'CSVWriter'|
D:\src\c\Tests\CPPMingW\main.cpp|67|note: because the following virtual functions are pure within 'CSVWriter':|
D:\src\c\Tests\CPPMingW\main.cpp|11|note: virtual void IContainer::loadDefaults()|
D:\src\c\Tests\CPPMingW\main.cpp|12|note: virtual void IContainer::storeDefaults()|
D:\src\c\Tests\CPPMingW\main.cpp|14|note: virtual bool IContainer::open()|
D:\src\c\Tests\CPPMingW\main.cpp|15|note: virtual bool IContainer::close()|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 6 second(s)) ===|
So the compiler expects me to reiplment all the functions from the base classes in the derived class as well.
So is there a solution to this, without having to define all these functions in the Reader/Writer class again? Of course I could implement dummies which just go down to the base class, but I consider this a bit clumsy and unneccessary overhead and I hope that there may be a better solution for this.
I hope I got it right. You have a kind of diamond problem. You inherit from the IContainer via two paths .
Normally in such cases you would have two instances of IContainer created per one instance of CSVReader, and the calls to IContainer methods would be ambiguous. In your case the path through IContainerReader does not have defined the mentioned functions. Virtual inheritance makes that only one instance is created.
Inheritance from IContainer should be declared as virtual. Virtual inheritance makes that every derivation from a class "will get combined together" (sorry for not very technical terms but this is how I understand it in simple english). In your case, only one copy of IContainer for both paths will be created, and the vtables will get filled from both paths.
This code compiles:
#include <iostream>
#include <string>
class IContainer
{
public:
IContainer() {};
virtual ~IContainer() {};
virtual void loadDefaults() = 0;
virtual void storeDefaults() = 0;
virtual bool open() = 0;
virtual bool close() = 0;
};
class IContainerReader : virtual public IContainer
{
public:
IContainerReader() {};
virtual ~IContainerReader() {};
virtual bool read() = 0;
};
class IContainerWriter : virtual public IContainer
{
public:
IContainerWriter() {};
virtual ~IContainerWriter() {};
virtual bool write() = 0;
};
class ContainerBase : virtual public IContainer
{
public:
ContainerBase() {}
virtual ~ContainerBase() {}
void loadDefaults() {}
void storeDefaults() {}
};
class CSVBase : public ContainerBase
{
public:
CSVBase() {}
virtual ~CSVBase() {}
void setFilename() {}
bool open() { return true; }
bool close() { return true; }
};
class CSVReader : public CSVBase, public IContainerReader
{
public:
CSVReader() {}
virtual ~CSVReader() {}
bool read() { return true; }
};
class CSVWriter : public CSVBase, public IContainerWriter
{
public:
CSVWriter() {}
virtual ~CSVWriter() {}
bool write() { return true; }
};
int main(int argc, char *argv[])
{
CSVReader r;
CSVWriter w;
IContainerReader *ir = &r;
IContainerWriter *iw = &w;
ir->open();
iw->open();
ir->read();
iw->write();
ir->close();
iw->close();
return 0;
}
parent class
class Test {
public:
Test(){};
virtual ~Test(){};
void print() { cout<<1<<endl;};
};
sub class .h define
class TestSub: public Test {
public:
TestSub();
virtual ~TestSub();
};
sub class .cpp implements
#include "TestSub.h"
TestSub::TestSub() {
}
TestSub::~TestSub() {
}
void TestSub::print(){
cout<<2<<endl;
}
int main(){
TestSub *t=new TestSub();
t->print();
}
why:
..\src\TestSub.cpp:17:21: error: no 'void TestSub::print()' member function declared in class 'TestSub'
You have 2 errors:
First you have to declare you function in TestSub as : void print();
Second you have to specify a return type for you implementation, C++ do not accept default return type such as C, so you must convert your implementation to void TestSub::print() {...}
print() funciton is not declared in TestSub class.
class TestSub: public Test {
public:
TestSub();
void print(); // add declaration.
virtual ~TestSub();
};
I guess you also intended to make Test::print virtual?
class Test {
public:
Test(){}
virtual ~Test(){}
virtual void print() { std::cout << 1 << std::endl;}
};
If you don't specify the return type C defaults to int as return type of a function. Which doesn't match the void return type of the declaration in the class.
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.