The ways to include another classes in a class file - c++

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()
{
}

Related

Forward declare free function in template class

I think I need some tutoring on templates, especially in conjunction with inheritance. I am well aware those two concepts don't play very well together.
We've wanted to get ride of clang tidy warnings, but I have no clue how to achieve it.
The abstracted code is below, please see https://godbolt.org/z/sPfx7Yhad to compile it.
The setting is, we have some abstract base class (Animal), and a specialized type (Dog).
A converter functionality can only be defined on the base class.
There is a templated reader class, which is templated with the actual specialized typed (Reader<Dog>).
However, clang-tidy complains when analyzing reader.h, as converter::convert is not known.
It's only known in main.cpp, by including converter.h before reader.h.
I have tried to forward declare the function by using template:
namespace converter
{
template<typename T>
void convert(const std::string& input, T& animal);
}
Which leads to linker errors, because now the linker is looking for a void convert(const std::string&, Dog&) implemenation, rather than using the void convert(cons std::string&, Animal&) overload. (see https://godbolt.org/z/x4cPfh6P4)
What can I do? How could I change the design to avoid the clang-tidy warning?
In general, I cannot add the actual includes to converter.h in reader.h, as that part is generic and the user shall be able to use the reader with their own types, by providing a custom converter functionality.
What I cannot change are classes Dog and Animal. They are autogenerated classes / libraries which we are using.
For anyone who is interested, the real world example can be found here https://github.com/continental/ecal/blob/master/samples/cpp/measurement/measurement_read/src/measurement_read.cpp
#include <string>
#include <iostream>
// animal.h
// class hierarchy with abstract base class
class Animal
{
public:
std::string name;
virtual std::string what() = 0;
};
// dog.h
class Dog : public Animal
{
public:
std::string what() override {return "dog";}
};
// animal_converter.h
// converting function
// #include <animal.h>
namespace converter
{
void convert(const std::string& input, Animal& animal)
{
animal.name = input;
}
}
// reader.h
// Templated class for reader functionality
template <typename T>
class Reader
{
public:
T read()
{
T output;
converter::convert("Anton", output);
return output;
}
};
// main.cpp
// #include dog.h
// #include animal_converter.h
// #include reader.h
int main()
{
Reader<Dog> reader;
std::cout << reader.read().name << std::endl;
}

One-Definition Rule Followed, but C++ throws Redefinition Error

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() {}

How to create a private static const string when using the pimpl idiom

Background
I have been learning how to implement the pimpl idiom using the newer c++11 method described by Herb Sutter at this page: https://herbsutter.com/gotw/_100/
I'm trying to modify this example by adding a member variable to the private implementation, specifically a std::string (although a char* has the same issue).
Problem
This seems to be impossible due to the use of a static const non-integral type. In-class initialization can only be done for integral types, but because it is static it can't be initialized in the constructor either.
A solution to this problem is to declare the private variable in the header file, and initialize it in the implementation, as shown here:
C++ static constant string (class member)
However, this solution does not work for me because it breaks the encapsulation I'm trying to achieve through the pimpl idiom.
Question
How can I hide a non-integral static const variable within the hidden inner class when using the pimpl idiom?
Example
Here is the simplest (incorrect) example I could come up with demonstrating the problem:
Widget.h:
#ifndef WIDGET_H_
#define WIDGET_H_
#include <memory>
class Widget {
public:
Widget();
~Widget();
private:
class Impl;
std::unique_ptr<Impl> pimpl;
};
#endif
Widget.cpp:
#include "Widget.h"
#include <string>
class Widget::Impl {
public:
static const std::string TEST = "test";
Impl() { };
~Impl() { };
};
Widget::Widget() : pimpl(new Impl()) { }
Widget::~Widget() { }
Compilation command:
g++ -std=c++11 -Wall -c -o Widget.o ./Widget.cpp
Note that this example fails to compile because the variable TEST cannot be assigned at declaration due to it not being an integral type; however, because it is static this is required. This seems to imply that it cannot be done.
I've been searching for previous questions/answers to this all afternoon, but could not find any that propose a solution that preserves the information-hiding property of the pimpl idiom.
Solution Observations:
In my example above, I was attempting to assign the value of TEST in the Impl class declaration, which is inside of Widget.cpp rather than its own header file. The definition of Impl is also contained within Widget.cpp, and I believe this was the source of my confusion.
By simply moving the assignment of TEST outside of the Impl declaration (but still within the Widget/Impl definition), the problem appears to be solved.
In both of the example solutions below, TEST can be accessed from within Widget by using
pimpl->TEST
Attempting to assign a different string into TEST, i.e.
pimpl->TEST = "changed"
results in a compiler error (as it should). Also, attempting to access pimpl->TEST from outside of Widget also results in a compiler error because pimpl is declared private to Widget.
So now TEST is a constant string which can only be accessed by a Widget, is not named in the public header, and a single copy is shared among all instances of Widget, exactly as desired.
Solution Example (char *):
In the case of using a char *, note the addition of another const keyword; this was necessary to prevent changing TEST to point to another string literal.
Widget.cpp:
#include "Widget.h"
#include <stdio.h>
class Widget::Impl {
public:
static const char *const TEST;
Impl() { };
~Impl() { };
};
const char *const (Widget::Impl::TEST) = "test";
Widget::Widget() : pimpl(new Widget::Impl()) { }
Widget::~Widget() { }
Solution Example (string):
Widget.cpp:
#include "Widget.h"
#include <string>
class Widget::Impl {
public:
static const std::string TEST;
Impl() { };
~Impl() { };
};
const std::string Widget::Impl::TEST = "test";
Widget::Widget() : pimpl(new Widget::Impl()) { }
Widget::~Widget() { }
Update:
I realize now that the solution to this problem is completely unrelated to the pimpl idiom, and is just the standard C++ way of defining static constants. I've been used to other languages like Java where constants have to be defined the moment they are declared, so my inexperience with C++ prevented me from realizing this initially. I hope this avoids any confusion on the two topics.
#include <memory>
class Widget {
public:
Widget();
~Widget();
private:
class Impl;
std::unique_ptr<Impl> pimpl;
};
/*** cpp ***/
#include <string>
class Widget::Impl {
public:
static const std::string TEST;
Impl() { };
~Impl() { };
};
const std::string Widget::Impl::TEST = "test";
Widget::Widget() : pimpl(new Impl()) { }
Widget::~Widget() { }
You might want to consider making TEST a static function which returns a const std::string&. This will allow you to defined it inline.
You could also replace const by constexpr in your example and it will compile.
class Widget::Impl {
public:
static constexpr std::string TEST = "test"; // constexpr here
Impl() { };
~Impl() { };
};
Update:
Well, it seems that I was wrong... I always store raw string when I want constants.
class Widget::Impl {
public:
static constexpr char * const TEST = "test";
};
Depending on the usage pattern, it might be appropriate or not. If not, then define the variable as explained in the other answer.

chess game - error in abstract class

#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;
// ^^^^^^^^

Error: Invalid base class C++

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.