2

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?

4 Answers4

4

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

Community
  • 1
  • 1
Rakib
  • 7,435
  • 7
  • 29
  • 45
  • What do you mean by definition? That they're classes? – user3668005 May 23 '14 at 07:53
  • @user3668005, 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. – Rakib May 23 '14 at 07:55
4

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.

Shoe
  • 74,840
  • 36
  • 166
  • 272
  • Okay, that makes sense. Turns out they're the only two classes in my project for which I don't have header files right now. I didn't know not having them would affect this. – user3668005 May 23 '14 at 07:55
4
#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

DanDan
  • 10,462
  • 8
  • 53
  • 69
2

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)

mjs
  • 2,837
  • 4
  • 28
  • 48