我正在尝试将战略设计模式作为练习来实施。我的课很简单:
class Fly
{
public:
Fly();
bool fly();
};
class CanFly : public Fly
{
public:
bool fly()
{
return true;
}
};
class CantFly : public Fly
{
public:
bool fly()
{
return false;
}
};
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;
}
#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;
}
#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;
}
#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;
^
任何人都可以帮助我吗?
由于
答案 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
派生的Dog
或Animal
,您需要提供对实际CanFly
和CantFly
的引用分别到他们的基础Animal
的构造函数。此外,除了{* 1}}之外,还有什
答案 2 :(得分:-2)
将您的fly.cpp
更改为fly.h
,Animal.cpp
应该#include<fly.h>
或者只需将myFly
定义为指针Fly* myFly
。