Could anyone, please, explain what can cause this error?
Error: Invalid base class
I've got two classes where one of them is derived from second:
#if !defined(_CGROUND_H)
#define _CGROUND_H
#include "stdafx.h"
#include "CGameObject.h"
class CGround : public CGameObject // CGameObject is said to be "invalid base class"
{
private:
bool m_bBlocked;
bool m_bFluid;
bool m_bWalkable;
public:
bool draw();
CGround();
CGround(int id, std::string name, std::string description, std::string graphics[], bool bBlocked, bool bFluid, bool bWalkable);
~CGround(void);
};
#endif //_CGROUND_H
And CGameObject looks like this:
#if !defined(_CGAMEOBJECT_H)
#define _CGAMEOBJECT_H
#include "stdafx.h"
class CGameObject
{
protected:
int m_id;
std::string m_name;
std::string m_description;
std::string m_graphics[];
public:
virtual bool draw();
CGameObject() {}
CGameObject(int id, std::string name, std::string description, std::string graphics) {}
virtual ~CGameObject(void);
};
#endif //_CGAMEOBJECT_H
I tried cleaning my project but in vain.
It is not valid to define an array (std::string m_graphics[]) without specifying its size as member of a class. C++ needs to know the size of a class instance in advance, and this is why you cannot inherit from it as C++ won't know at runtime where in the memory the members of the inheriting class will be available.
You can either fix the size of the array in the class definition or use a pointer and allocate it on the heap or use a vector<string> instead of the array.
Related
Very strange redefinition error in C++, especially as every other file including main is error-free.
I have my headers (various animals) and an implementation file "animals.cpp".
My headers follow the format:
class Mammal : public Animal{
public:
Mammal(){} //empty constructor
virtual ~Mammal(){} // destructor
void createNewMammalObject(std::string name, std::string trackingNum, std::string nurse, std::string subType, std::string type){}
std::string getSubtype() {}
void setSubtype(std::string subType){}
int getNursing(){}
void setNursing(int nursing){}
void setType(std::string type){}
int getNumEggs(){}
protected:
int nursing;
};
And implementation in the implementation file looks like:
Mammal::Mammal() {} //empty constructor
virtual Mammal::~Mammal(){} // destructor
void Mammal::createNewMammalObject(std::string name, std::string code,std::string nurse,std::string subType, std::string type){
this->setNursing(nursing);
this->setSubType(subType);
this->createNewAnimalObject(name, trackingNum,subType,type);
}
std::string Mammal::getSubtype() {
return subType;
}
void Mammal::setSubtype(std::string subType) {
this->subType = subType;
}
int Mammal::getNursing() {
return this->nursing;
}
void Mammal::setNursing(int nursing) {
this->nursing = nursing;
}
void Mammal::setType(std::string type){
this->type = type;
}
int Mammal::getNumEggs() {
return 0;
}
My #includes for the implementation file are:
#include "animal.h"
#include "oviparous.h"
#include "mammal.h"
#include "crocodile.h"
#include "goose.h"
#include "pelican.h"
#include "bat.h"
#include "seaLion.h"
#include "whale.h"
All headers and implementation follow this format to follow the One-Definition, except for animal.h which is an abstract class and does contain function definitions. All other functions are definitely only defined once. However, after building the project, EVERY function in the implementation file is saying it's a redefinition and pointing back to the headers as the original definition. I'm incredibly confused. Is this an Eclipse problem? Should my abstract class be defined in my implementation file like the other headers?
Regarding your header file (focussing on one line but they pretty much all have the same problem):
std::string getSubtype() {}
// ^^
// see here
This is a definition of a function with an empty body, a non-definition declaration would be:
std::string getSubtype();
The fact that you're defining functions in both the header and implementation file is almost certainly the cause of your ODR violations.
And just two other points, neither necessarily fatal:
First, it's normal to set up the base class stuff first so that derived classes can override specific properties. That would result in a reordered (after also fixing the nurse/nursing discrepancy):
#include <string>
void Mammal::createNewMammalObject(
std::string name,
std::string code,
std::string subType,
std::string type,
std::string nursing // moved to end, just a foible of mine.
) {
this->createNewAnimalObject(name, trackingNum, subType, type);
// Could now modify below any of those items in previous line.
this->setNursing(nursing);
this->setSubType(subType);
}
Second, it's usual for the constructor to do as much work as possible, rather than having some function set things up. The latter leads to the possibility that a constructed object may be in some weird unusable state if you forget to call that function.
I would be looking at something more along the lines of:
#include <string>
class Animal {
public:
Animal(
std::string name,
std::string trackingNum,
std::string subType,
std::string type
)
: m_name(name)
, m_trackingNum(trackingNum)
, m_subType(subType)
, m_type(type)
{
// Other less important initialisation and possibly also
// throwing exception if any of those four above are invalid.
}
private:
std::string m_name;
std::string m_trackingNum;
std::string m_subType;
std::string m_type;
};
class Mammal :Animal {
public:
Mammal(
std::string name,
std::string trackingNum,
std::string subType,
std::string type,
std::string nursing
)
: Animal(name, trackingNum, subType, type)
, m_nursing(nursing)
{
// Ditto on more initialisation and throwing
// for bad nursing value.
}
private:
unsigned int m_nursing;
};
int main() {}
I am learning c++ and confused about the ways to include another class in current class. For example, I am wondering whether class QuackBehavior equals to #include <QuackBehavior.h>. If they are equal, what are the differences between these two ways? The code is :
#include <string>
class QuackBehavior;
class Duck {
public:
Duck();
virtual ~Duck() {};
virtual void performQuack();
virtual std::string getDescription() = 0;
std::string getName() {return m_name;}
void setName(std::string name ) {m_name = name;}
void setQuackBehavior(QuackBehavior * behavior);
protected:
std::string m_name;
QuackBehavior * m_quackBehavior;
};
Thank you so much.
The two are not equal:
class QuackBehavior; is considered a forward-declaration, and simply informs the compiler that there is a class called QuackBehavior. This can only be used if you are using QuackBehavior as a pointer or reference:
class B;
struct C;
struct A
{
shared_ptr<B> getB() const { return b; }
const C& getC() const;
private:
shared_ptr<B> b;
};
Here the compiler doesn't need to know any implementation details of C and B, only that they exist. Notice that it's important to tell the compiler whether it's a class or struct also.
#include <QuackBehavior> is an include, and essentially copies+pastes the entire file into your file. This allows the compiler and linker to see everything about QuackBehavior. Doing this is slower, as you'll then include everything that QuackBehavior includes, and everything those files include. This can increase compile times dramatically.
Both are different, and both have their places:
Use forward-declaration when you don't need to know the implementation details of a class just yet, only that they exist (e.g. use in pointers and references)
Include the file if you are declaring an object, or you need to use functions or members of a class.
In QuackBehavior.h file, forwarding declaring QuackBehavior class will suffice.
#include <string>
class QuackBehavior; // tells the compiler that a class called QuackBehavior exists without any further elaborations
class Duck {
public:
Duck();
virtual ~Duck() {};
virtual void performQuack();
virtual std::string getDescription() = 0;
std::string getName() {return m_name;}
void setName(std::string name ) {m_name = name;}
void setQuackBehavior(QuackBehavior * behavior);
protected:
std::string m_name;
QuackBehavior * m_quackBehavior;
};
However in QuackBehavior.cpp file, you have to use #include"QuackBehavior.h" so that the compiler can find the implementation member functions
#include <QuackBehavior.h>
#include <string>
duck::duck()
{
}
#pragma once
#include <string>
#include <iostream>
using namespace std;
class Chess_tool
{
public:
Chess_tool(string color, char name);
virtual bool legal_movement(int source[], int dest[]) const = 0;
private:
string _color;
char _name;
};
Im trying to create chess game, so I create abstract class for chess tool (queen, king, rook...)
I also created king tool to check my code:
#pragma once
#include "Chess_tool.h"
class King : Chess_tool
{
public:
King(string color, char name);
virtual bool legal_movement(int source[], int dest[]);
};
and I create game_board class:
#pragma once
#include "Game_board.h"
#include "Chess_tool.h"
#include <iostream>
#define BOARD_SIZE 8
using namespace std;
class Chess_tool;
class Game_board
{
public:
Game_board();
~Game_board();
void move(string panel);
protected:
Chess_tool* _board[BOARD_SIZE][BOARD_SIZE];
};
the problem is here, when i try to add object to the matrix its show me error :
1 IntelliSense: object of abstract class type "King" is not allowed:
pure virtual function "Chess_tool::legal_movement" has no overrider
#pragma once
#include "Chess_tool.h"
#include "Game_board.h"
#include "King.h"
using namespace std;
enum Turn { WIHTE, BLACK };
class Manager : Game_board
{
public:
Manager();
~Manager();
virtual bool legal_movement(int source[], int dest[]) const = 0;
};
....
#include "Manager.h"
Manager::Manager()
{
_board[0][0] = new King();
}
The member function in the base class is const-qualified, not in the derived class.
So these are not the same functions through inheritance. You've declared a new virtual function, not overriden the first one.
Add const to the second one so that it actually override the base class function.
Remember that for virtual function overriding to kick in, there are a few condition to actually satisfy. They must have:
the same name
the same return type
the same parameters count and type
the same const-qualification (our case here)
a few other minor things (for example, compatible exceptions specifications)
If any condition isn't satisfied, you create a very similar, but different, function for the compiler.
With C++11, you should use override for the functions you want to override, so the compiler knows your intention and tells you that you've made a mistake. E.g.:
virtual bool legal_movement(int source[], int dest[]) override;
// ^^^^^^^^
I have two clases Pet and Person
Here is the Person.h:
#ifndef PERSON_H
#define PERSON_H
#include <list>
class Pet;
class Person
{
public:
Person();
Person(const char* name);
Person(const Person& orig);
virtual ~Person();
bool adopt(Pet& newPet);
void feedPets();
private:
char* name_;
std::list<Pet> pets_;
};
#endif
And here is the Pet.h
#ifndef PET_H
#define PET_H
#include <list>
#include "Animal.h"
class Person;
class Pet : public Animal
{
public:
Pet();
Pet(const Pet& orig);
virtual ~Pet();
std::list<Pet> multiply(Pet& pet);
private:
std::string name_;
Person* owner_;
};
#endif
The problem that i have is this:
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/list.tcc:129: error: invalid use of undefined type `struct Pet'
Person.h:13: error: forward declaration of `struct Pet'
I fixed trying to put this std::list<Pet>* pets_; but when i tried to call list functions always have a link problem. My question is how a have to include a list inside a class that contains objects from another class.
The standard requires that, except where explicitly stated, you use complete types with the library templates. This basically inhibits your design (where each object maintains by value a list of the other type).
You can work around this by using [smart] pointers (either a pointer to the container or container of pointers).
When I try the two forms of constructor in classes of derivation hierarchy, the result turns out to be different. Could anybody tell me why? Below are the test code.
//Person.h
#ifndef PERSON_H_
#define PERSON_H_
#include<string>
using std::string;
class Person{
private:
string firstname;
string lastname;
public:
Person(const char *fn="NoName", const char *ln="NoName"); //A
Person(const string &fn, const string &ln);
virtual ~Person(){}
};
class Gunslinger:virtual public Person{
private:
int notchnum;
public:
Gunslinger(const char*f="unknown",const char*n="unknown",int not=0);//B
virtual ~Gunslinger(){}
};
class PokerPlayer:virtual public Person{
public:
PokerPlayer(const char*fn="unknown", const char*ln="unknown");//C;
virtual ~PokerPlayer(){}
};
class BadDude:public Gunslinger,public PokerPlayer{
public:
BadDude(const char*fn="unknown", const char*ln="unknown", int notc=0);//D
};
#endif
//PersonDefinition.cpp
#include"Person.h"
#include<iostream>
#include<cstdlib>
using std::cout;
using std::endl;
using std::cin;
Person::Person(const char*fn, const char*ln):firstname(fn),lastname(ln){
}
Person::Person(const string &fn,const string &ln):firstname(fn),lastname(ln){
}
Gunslinger::Gunslinger(const char*fn,const char*ln, int not):Person(fn,ln),notchnum(not){
}
PokerPlayer::PokerPlayer(const char*fn,const char*ln):Person(fn,ln){
}
BadDude::BadDude(const char*fn, const char*ln, int notc):Person(fn,ln),PokerPlayer(fn, ln),Gunslinger(fn,ln,notc){
}
//PersonTest.cpp
#include<iostream>
#include "Person.h"
int main(){
Person a("Jack","Husain");
PokerPlayer b("Johnson","William",8);
Gunslinger c("Mensly","Sim");
}
So, here is the problem. The program above fails to compile with the default constructor with default value for all argument and throws an error message saying that "expected ',' or '...' before '!' token", but if I replace the default constructor in Line A,B,C,D with the form without argument, the program compiles and run successfully.Could anyone tell me why? Below is the error message.
You did not implement all the constructors. For instance, you declared a constructor PokerPlayer::PokerPlayer(char*, char*) but you are trying to create a PokerPlayer with PokerPlayer b("Johnson","William",8); (i.e. you never declared a constructor which takes the third argument). The declaration you want for that previous line to work is PokerPlayer::PokerPlayer(char*, char*, int);
Furthermore, you have the exact opposite problem when trying to declare a GunSlinger. Your GunSlinger class requires the third parameter and you are trying to declare it without that argument.
Even though your base class supports several types of constructors, each derived class must also have every constructor you wish to use on it explicitly declared/implemented (with the exception of the default constructor).
EDIT
Here is some semi-functional code:
class PokerPlayer : public Person
{
...
PokerPlayer(char* fname, char* lname, int val);
...
};
Implementation
PokerPlayer::PokerPlayer(char* fname, char* lname, int val) : Person(fname, lname, val)
{
// Anything else we should do...
}