我有一个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;
}
和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;
}
我有一个filter.h,我想从Source和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;}
};
然而,编译器给出了无效使用不完整类型的错误&#39; class Source&#39;并且&#39;类Sink&#39;。我也得到了相同类的前向声明错误。这些类最初的函数直接在public
中定义,所以我把它们移出去了,但这对此没什么帮助。将Public和Sink明确设置为公众也没有帮助。发生了什么事?
答案 0 :(得分:4)
转发声明只允许编译器知道名称存在,但它不会告诉任何有关名称定义的信息。为了继承,基类&#39;定义必须是已知的。您必须在 filter.h 中包含标头,以便编译器可以看到父类的定义。
修改强>
声明表示存在名称,定义表示名称的外观。对于类定义,它表示类包含的内容,它的成员,大小等。当一个类被另一个继承时,编译器类将基类的成员放在派生类中。所以它必须知道基类是什么样的。通过包含定义基类的头,编译器实际上将定义放在包含的文件中,因此它知道基类。
正如其他人指出您的私下继承一样,我建议您阅读is-a has-a关系和difference between private and public inheritance
答案 1 :(得分:4)
这是因为在你的filter.h
中你提出了一个不完整的声明:
class Source;
class Sink;
但没有定义它们。编译器需要知道两者的大小,以便计算Filter
的大小:
class Filter : Source, Sink
{
public:
Filter() {std::cout << "Constructing filter." << std::endl;}
};
解决方案是包含两者的头文件。为此,您可能需要将声明与源文件和源文件中的实现分开。
答案 2 :(得分:4)
#include "sink.h"
#include "source.h"
应该把你排除在外。
这一行:
class Filter : Source, Sink
这是私有继承,几乎总是你不想要的(你不能以多态方式使用该类)。
您可能需要将其更改为
class Filter : public Source, public Sink
答案 3 :(得分:2)
这里有两个问题
第一个,正如其他人所提到的那样,您需要包含Sink和Source的标头。目前,您只有前向声明,它将允许您使用指针,但不能派生或实例化。编译器不知道它提供的大小,方法或构造方法。
第二个问题,一旦包含标题,您将会遇到的问题是Sink类中有一个纯虚函数。这使它成为一个抽象的基类。 你需要从这个(你有)派生并在派生类中实现Execute方法(你没有)