C ++:字段类型不完整

时间:2015-07-18 09:46:56

标签: c++ inheritance design-patterns

我正在尝试将战略设计模式作为练习来实施。我的课很简单:

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

任何人都可以帮助我吗?

由于

3 个答案:

答案 0 :(得分:2)

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

但这不是你真正想做的事。 您的目的是使用多态,因此您需要通过引用或指针传递对象。

你的动物类应该是:

class Animal
{
    Fly &myFly;

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

通过这种方式,您可以将任何Fly,CanFly或CantFly对象传递给Animal对象。

您还需要重新组织代码。您需要将类定义分隔为头文件。例如:

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

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

然后你需要在cpp中包含标题。例如:

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

请注意以下定义之间的区别:

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

返回存储在myFly中的对象副本。

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

返回对象myFly

的常量引用

另外,也许,您根本不需要Fly, CanFly, CantFly个课程。类Bird, Dog已经“知道”它们是否可以飞行。当然,你正在做一个练习但是Fly,CanFly等似乎在这里是多余的和人为的。

答案 1 :(得分:1)

要使用class,必须使用定义。像

这样的陈述
class Fly;

不是定义,只是声明。已声明的类不能使用,但您可以定义指向此类的指针和引用。

因此,为了使代码正常工作,您应该将代码拆分为包含类定义和源文件(.cpp)的头文件(.hpp),其中包含头中声明的任何类成员的(非内联)定义

此外,您似乎想要使用多态,但忘记将成员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

但是,我不喜欢这种模式。问题是,为了定义从Bird派生的DogAnimal,您需要提供对实际CanFlyCantFly的引用分别到他们的基础Animal的构造函数。此外,除了{* 1}}之外,还有什

答案 2 :(得分:-2)

将您的fly.cpp更改为fly.hAnimal.cpp应该#include<fly.h>或者只需将myFly定义为指针Fly* myFly