Why are these classes incomplete? - c++

I have a source.C:
#include "image.h"
#ifndef SOURCE_H
#define SOURCE_H
class Source
{
private:
Image* img;
public:
virtual void Execute()=0;
Image* GetOutput();
};
#endif
Image* Source::GetOutput()
{
return this->img;
}
and a sink.C.
#include "image.h"
#ifndef SINK_H
#define SINK_H
class Sink
{
private:
Image* img1;
Image* img2;
public:
void SetInput(Image* input1);
void SetInput2(Image* input2);
};
#endif
void Sink::SetInput(Image* input1)
{
this->img1 = input1;
}
void Sink::SetInput2(Image* input2)
{
this->img2 = input2;
}
I have a filter.h that I want to inherit from Source and Sink:
#include "image.h"
#include <iostream>
#include <stdlib.h>
class Source;
class Sink;
class Filter : Source, Sink
{
public:
Filter() {std::cout << "Constructing filter." << std::endl;}
};
However, the compiler gives me errors of invalid use of incomplete types 'class Source' and 'class Sink'. I also get an error of forward declaration for those same classes. The classes originally had their functions defined directly in public, so I moved them out, but that didn't help with this. Explicitly setting Source and Sink as public didn't help either. What's going on?

#include "sink.h"
#include "source.h"
should sort you out.
Also this line:
class Filter : Source, Sink
This is private inheritance, which is almost always what you don't want (you won't be able to use the class polymorphically).
You may need to change this to
class Filter : public Source, public Sink

It's because in your filter.h you are giving an incomplete declaration:
class Source;
class Sink;
but not defining them. The compiler needs to know the size of both in order to calculate the size of Filter in:
class Filter : Source, Sink
{
public:
Filter() {std::cout << "Constructing filter." << std::endl;}
};
The solution is to include the header files for both. And for that you'll probably need to separate declaration from implementation in header files and source files.

Forward declaration only lets compiler to know that a name exists, but it does not tell anything about the definition of the name. In order to inherit, the base class' definition must be known. You have to include the headers in filter.h so that compiler can see the definition of the parent classes.
Edit
Declaration means a name exists, definition means what the name looks like. For class definition, it means what the class contains, it's members, size etc. When a class is inherited by another, the compiler kind of places the members of base class in the derived class. So it has to know what the base class looks like. By including the header where base class is defined, compiler actually places the definition in the included file, hence it knows about the base class.
As others pointed out about your privately inheritance, I recommend you to read is-a has-a relationship and difference between private and public inheritance

There are two problems here
The first, as mentioned by others is that you need to include the headers for Sink and Source. At the moment you only have a forward declaration, which will let you use a pointer, but not derive from, or instantiate. The compiler doesn't know the size, or what methods it provides, or how to construct.
The second problem, which you will hit once you include the headers, is that the Sink class has a pure virtual function in it. This makes it an abstract base class.
You need to derive from this (which you have) and implement the Execute method in the derived class (which you haven't)

Related

How to avoid "redefinition; different basic types" when trying to implement PIMPL idom

I am trying to use the PIMPL idiom -- hiding the implementation details of a class from the user. I also want to go one step further, by hiding the actual name of the implementation class. This should also allow me to quickly swap the implementation class by changing a single line of code.
My approach is as follows:
In the header file I define a Public class and declare a proxy name Implementation of what would be the implementation class.
X.h:
#pragma once
namespace detail {
class Implementation;
}
class Public {
public:
Public();
void foo();
private:
detail::Implementation* data;
};
Within the implementation I define the actual implementation class (under a different name) and then use a typedef to set Implementation to be that class of my choosing.
X.cpp
#include <iostream>
#include "X.h"
namespace {
class Private { //the actual implementation class. Everything about it, including its name, should be hidden
public:
void foo() { std::cout << "Hello world!" << std::endl; }
};
}
namespace detail {
typedef Private Implementation; //set Private as the actual Implementation
}
Public::Public() : data(new detail::Implementation()) {}
void Public::foo() {
data->foo();
}
Unfortunately I get an error:
error C2371: 'detail::Implementation': redefinition; different basic types
in the typedef line. But in both locations (cpp and h files) I declare a class; one with a definition provided, the other without. So what am I missing?
If typedef (or C++11 using) cannot be used because of reasons, how else can I achieve my goal?
I have seen similar questions about the same error, but all I found were some trivial errors, such as:
Error C2371: redefinition; different basic types - why? : uses a name before its definition
Redefinition; different basic types (typedef struct), or Redefinition different basic types => typedef : an include guard is forgotten
Put your typedef in your header file and remove the declaration of Implementation.
You are declaring Implementation twice. Once at class Implementation; and again at typedef Private Implementation;
If you want to hide the Private type make Public templated:
template<typename Implementation>
class Public
{
......
Implementation * data;
......
};
Then in your cpp you can declare it with your private implementation as :
Public<Private> my_thing;
Even better you can hide the template using typedef as you originally planned:
typedef Public<Private> ExposedClass
define the actual implementation class (under a different name) and then use a typedef to set Implementation to be that class of my choosing.
That's the problem. You can't. A typedef name is not a class. By saying class Implementation, you promise Implementation will be defined as an actual class, not a typedef name.
Get rid of the typedef and rename Private to Implementation.

Can Class Functions Have Parameters That Are Different Class Objects?

Let's say I have 2 classes, player and npc. In the header file for class player, could I have a function that has an npc class object as a parameter?
For instance:
player.h:
void somefunc(npc npc1);
Yes, this is allowed, as long as a definition or forward declaration for the type has been encountered yet. You can also have pointers or references to other types, and even parameters of the same class' type.
class A {};
class B {
public:
void funcA(A a) {}
void funcAPtr(A* p) {}
void funcARef(A& r) {}
void funcB(B b) {}
};
// ...
A a;
B b;
b.funcA(a);
This is actually one of the key tenets of object-oriented programming.
In your case specifically, you would want to have a definition for npc first, so it might look something like this:
// npc.h
class npc {};
// -----
// player.h
#include "npc.h"
class player {
public:
void somefunc(npc npc1);
};
Or, if you have function bodies in a .cpp file, you can just put a forward declaration in the header, and include npc.h in the source file. This is usually safer, especially in cases where you may encounter circular dependency issues.
// npc.h
class npc {};
// -----
// player.h
class npc;
class player {
public:
void somefunc(npc npc1);
};
// -----
// player.cpp
#include "player.h"
#include "npc.h"
void player::somefunc(npc npc1) {}
// Note that "npc"'s header must be included before the type is actually used.
// For example, it needs to be included before the function's body, even though a
// forward declaration is enough for the function's prototype to work properly.
Yes, it's totally possible and one thing I'd like to add is that is generally a good thing to receive the parameter as a pointer to a object of that class since you'll not always want to make a copy of an entire object in memory.
Besides that, you could (and should depending on the case) take the parameter as a pointer to a const object so that the method can access whatever it needs from the object without making a copy of it and without modifying it's members.

c++ forward declaration of a static class member

I have a class:
class M {
public:
static std::string t[];
};
with an initialization that comes later. I want to use the M::t later in a different class (header file):
class Use {
public:
void f() { std::cout << M::t[0] << std::endl; }
};
Is there any way to achieve this without including the whole class M for the header file of the Use? I understand that forward declarations do not allow accessing class members, however this beauty is a static one, so it shouldn't be a huge problem for the compiler..
No, you can't. You can either include the header in the header, or separate the implementation Use::f in an implementation file and include M's header there.
There are no partial classes like in C#, where you can define a class in several files.
Since you are making it a public static member, why don't you create a namespace and embed it there?
namespace myns{
std::string t[];
}
You can access it from anywhere then, just like you would have done with a public static class member.
Forward declarations only allow you to use forward-declared-class pointers or references, not members! If you want to use class members like in your example you have to include the class header, even if it's static.
Here is the solution if you don't want to include M.h in your Use.h header:
Use.h
class Use {
public:
void f();
};
Use.cpp
#include "M.h"
#include "Use.h"
void Use::f() {
std::cout << M::t[0] << std::endl;
}
Also, you have to know it's a bad habit to write code in header files, except of course for inline and templates.

C++ object hierarchy - how to manage circular dependencies?

I want to make two classes: an object and an object_manager, but I'm confused about how they should see/include each other. I've heard that it's forbidden for two headers to include each other and if my code dependencies has circles then it's a bad code design and usually it should be like a hierarchy structure (town->house->furniture and furniture shouldn't know about town existence).
But here I have the object_manager which knows and holds all the objects, and the objects should have an option to create new objects, but then they should call the object_manager which will force them to know about it existence and this will create a circle in the structure, which is bad.
It's like one process wants to create a new process by calling the OS system calls, so the OS and the process knows about each other.
Is there a way I can implement this in the right code design, or should it just be bad sometimes?
I thought maybe the objects should have a special place where they will store all their "system calls", and the object_manager will check it from time to time, but maybe there is a better way.
Use forward declaration:
class ObjectManager;
class Object
{
private:
ObjectManager* m_objManager;
....
public:
....
};
In .cpp file you can include the ObjectManager.h
Also instead of ObjectManager make the interface which will give you more abstraction for implementation IObjectManager.
Actually it is possible to implement the two. And no it's not really bad. Here is some partial code.
let's say you have a header file
myobject.h
#ifndef _MYOBJECT
#define _MYOBJECT
// Declare the Object Manager class in it.
class MyObjectManager; // forward declaration
class MyObject {
MyObjectManager manager;
registerSelf(MyObjectManager &m);
}
#endif _MYOBJECT
Now for the ObjectManager header
#ifndef _MYOBJECT_MANAGER
#define _MYOBJECT_MANAGER
class MyObject; // forward declaration
class MyObjectManager {
private:
List list[];
public:
registerObject(MyObject &o);
};
#endif
Implementation of objectmanager
#include <myobject>
#include <myobjectmanager>
MyObjectManager::manageMyObject(MyObject &o) {
list += o; /* etc. */
}
Implementation of object
#include <myobject>
#include <myobjectmanager>
MyObject::registerSelf(MyObjectManager &manager) {
this.manager = manager;
manager.registerObject(*this);
}
There are many cases where classes need to know about each other. The only issue with this is they have to know about each other partially or at least one class does. The way the issue is generally solved is using forward declarations . The only sticky issue is in class A you can't declare a member that has a type of class B only a pointer or a reference to Class B.
class B;
class A
{
B* oB;
};
class B
{
A oA;
}:
Some general recommendations to remove the coupling between headers follow:
Forward Declare what you can. Sometimes your A class uses others classes (X,Y,..) only by passing references or pointers. So in your A.h you can declare methods that use these X,Y return or argument types without the compiler needing to know the complete type. That means that A.h does not need to include X.h or Y.h
Use PImpl idioms, Sometimes the best way to decouple implementation from interface (without using virtual or abstract classes) is doing something like:
Foo.h
class Foo {
struct Impl;
Impl* m_impl;
public:
Foo();
void SomeMethod();
}
Foo.cpp
#include "X.h"
struct Foo::Impl {
/* actual implementation */
...};
Foo::Foo() : m_impl( new Foo::Impl() ) {};
void Foo::SomeMethod() {
m_impl->SomeMethod();
}
What you're describing is an object that can only exist inside another object.
A good way to implement this is with nested classes:
class object_manager {
public:
class object { // object_manager::object. public allows it to be used outside of manager
public:
void foo() {
object* t = construct(); // can call object_manager methods
}
};
private:
object my_objects[5]; // can create objects
static object* construct() { return NULL; }
};
Keep in mind that you can still have 2 cpp files for object and object_manager.
The CPP files can include each other's headers without causing a compile problem (whether it's correct from a design point of view is a different matter, but should be ok in yur case). This means they can call each other's methods, etc.
Regarding the header files, the "object manager" header will most likely include the "object" header because the "object manager" class needs to work with "object" class instances. If the "object" header file needs to know about the "object manager" class, place a forward declaration for the "object manager" in the "object" header file. That way you can use pointers and references to the "object manager" in the "object" header file without creating a circular include dependency.

C++ classes refer to each other ( => error + field '...' has incomplete type)

Classes in my application work like this: Creature has few fields with Actions. When these Actions must be run Creature calls someActionField->do(this). Action has method viod do(Creature* cr) and all information about what to do with this Creature.
So, Creature must have Action field and know that Action has do method. Action must know that Creature has such fields like: Will, HP, etc...
I've got
creature.h
#include "effect.h"
#include "heedupdate.h"
namespace Core
{
class Action;
class Creature : public NeedUpDate
{
public:
virtual ~Creature();
int HP;
Action onHit;
Action onDie;
// ...
};
}
#endif
And action.h
#include "creature.h"
namespace Core
{
class Action
{
public:
Action();
virtual void _do(Creature* cr);
virtual ~Action();
};
But in this case field `onDie' has incomplete type error appears. If I include action.h into creature.h - I use files 'before each other'.
You Creature class has members of type Action. The compiler needs to know the full definition of the Action class to compile that - an incomplete type as produced with a forward declaration is not enough.
The Action class only requires a pointer to a Creature object in that header. In that case, the compiler only needs to know that Creature will be defined at some point.
In your specific case, you could get away with inverting the order in which you declare your classes.
(i.e. forward-declare Creature in action.h, and include action.h in creature.h)
in action.h put class Creature; and in the other one #include "action.h"
For pointers you don't need complete definition because it's just a pointer and the compiler can generate "code" for it. If you use a simple class/struct the compiler has to have knowledge of the type because it needs to know how big it is.
When you forward declare a type, all the compiler know is that this type exists; it knows nothing about its size, members, or methods, hence it is called an Incomplete Type
You cannot use an incomplete type to declare a member(because compile needs to know the size of the type while declaring it) and hence you get the error.
You don't need to #include "creature.h" in action.h but you just need to forward declare class Creature. You do need to #include "action.h" in creature.h
Your header files should have the following construct:
creature.h
#include "effect.h"
#include "action.h"
#include "heedupdate.h"
action.h
class creature;
This makes use of two rules:
One can Declare functions or methods which accepts/return incomplete types:
action.h only declares a function which accepts an Incomplete type(Creature)
One cannot declare a member to an incomplete type.
creature.hhas to include action.h because it declares a member of type Action.
You don't need to #include "creature.h" in action.h. All you need is a forward declaration of class Creature. You do need to #include "action.h" in creature.h because onHit and onDie are instances of Action.
Use references, or pointers :
#include "effect.h"
#include "heedupdate.h"
namespace Core
{
class Action;
class Creature : public NeedUpDate
{
public:
virtual ~Creature();
int HP;
Action & onHit;
Action & onDie;
// ...
};
}
#endif
This way you can break dependencies and not need a fully declared Action class