C++:字段的类型不完整

C++: Field has incomplete type

我正在尝试将策略设计模式作为练习来实施。我的 类 非常简单:

1) Fly.cpp

class Fly
{
    public:
        Fly();
        bool fly();
};

class CanFly : public Fly
{
    public:
        bool fly()
        {
            return true;
        }
};

class CantFly : public Fly
{
    public:
        bool fly()
        {
            return false;
        }
};

2) Animal.cpp

class Fly;

class Animal
{
    Fly myFly;

public:
    Animal(Fly f);
    void setFly(Fly f);
    Fly getFly();
};

Animal::Animal(Fly f)
{
    myFly = f;
}

void Animal::setFly(Fly f)
{
    myFly = f;
}

Fly Animal::getFly()
{
    return myFly;
}

3) Dog.cpp

#include <iostream>
using namespace std;

class Animal;

class Dog : public Animal
{
    public:
        Dog(Fly f);
};

Dog::Dog(Fly f)
{
    setFly(f);
    cout << "Dog : " << getFly().fly() << endl;
}

4) Bird.cpp

#include <iostream>
using namespace std;

class Animal;

class Bird : public Animal
{
    public:
        Bird(Fly f);
};

Bird::Bird(Fly f)
{
    setFly(f);
    cout << "Bird : " << getFly().fly() << endl;
}

5) AnimalTest.cpp

#include <iostream>
using namespace std;

class Dog;
class Bird;
class CanFly;
class CantFly;

int main()
{
    Fly f1 = new CanFly();
    Fly f2 = new CantFly();

    Bird b(f1);
    Dog d(f2);

    return 0;
}

我在构建代码时遇到的错误是:

Animal.cpp:5:6: error: field 'myFly' has incomplete type 'Fly'
  Fly myFly;
      ^

谁能帮我看看为什么?

谢谢

将您的 fly.cpp 更改为 fly.h,在 Animal.cpp 中您应该 #include<fly.h> 或者将您的 myFly 定义为指针 Fly* myFly

不完整类型错误意味着编译器看不到 class 的定义,只有声明。 如果您创建 object 或按值传递 object,则需要向编译器提供 class 的定义。您确实创建了 objects 并通过值传递它们,因此您需要包含传递到 cpp 文件中的相关 classes 的定义。

但这不是你真正想做的。 您的意图是采用多态性,因此您需要通过引用或指针传递 objects。

您的动物 class 应该是:

class Animal
{
    Fly &myFly;

public:
    Animal(Fly &f);
    void setFly(Fly &f);
    Fly const &getFly();
};

通过这种方式,您可以将 Fly、CanFly 或 CantFly object 中的任何一个传递给 Animal object。

您还需要重新组织您的代码。您需要将 class 个定义分成 header 个文件。例如:

//Animal.h
class Fly; <=== Declaration. OK here.
class Animal
{
    Fly &myFly;

public:
    Animal(Fly &f);
    void setFly(Fly &f);
    Fly const &getFly();
};

然后你需要在cpp中包含headers。示例:

#include "Animal.h"
class Dog : public Animal <=== Compiler needs definition of Animal here
{
    public:
        Dog(Fly f);
};

注意以下定义的区别:

Fly Animal::getFly()
{
    return myFly;
}

Returns 一份 object 存储在 myFly 中。

Fly const &Animal::getFly()
{
    return myFly;
}

Returns 对 object myFly

的常量引用

此外,也许您根本不需要 Fly, CanFly, CantFly classes。 类 Bird, Dog 已经 "know" 如果他们能飞或不能飞。当然,你正在做运动,但 Fly、CanFly 等在这里似乎是多余的和做作的。

为了使用 class,它的 定义 是必需的。像

这样的语句
class Fly;

不是定义,而只是一个声明。已声明的 class 不能使用,但您可以定义指向此类 class.

的指针和引用

因此,为了让您的代码正常工作,您应该将代码拆分为包含 class 定义的 header 文件 (.hpp) 和包含 (non-inline) 在 header 中声明的任何 class 成员的定义。

另外,你好像想使用多态,但是忘了把成员bool Fly::fly()声明为virtual。我想你想要的是

// file Fly.hpp
struct Fly
{
  virtual bool fly() const = 0;
};

struct CanFly : Fly
{
  bool fly()
  { return true; }
};

struct CantFly : Fly
{
  bool fly()
  { return false; }
};

然后

// file Animal.hpp
struct Fly;                  // forward declaration
struct Animal
{
  const Fly*const myFly;      // use pointer to forwardly declared class
                              // const data member is public (serves as getter)
  bool fly() const;
protected:
  Animal(Fly const&f);
  // no setter: an Animal cannot change its flying behaviour
};

// file Animal.cpp
#include "Fly.hpp"
#include "Animal.hpp"

Animal::Animal(Fly const&f)
: myFly(&f) {}

bool Animal::fly() const
{ return myFly->fly(); }       // polymorphic call

不过,我不喜欢这种模式。问题是,为了定义从 Animal 派生的 BirdDog,您需要提供对实际 CanFlyCantFly 的引用,分别传递给它们基数 Animal 的构造函数。而且,Animal除了能不能飞之外,没有什么可说的了,为什么还有这个classAnimal(除了Fly)?