我正在尝试用C ++学习设计模式。我正在实施OReilly's Head First Design Patterns
关于Duck问题的第一章中给出的程序。请耐心等待,这是一个很长的问题。
无论如何,我试图创建以下2个接口:
class QuackBehavior
{
public:
virtual void quack() = 0 ;
};
class FlyBehavior
{
public:
virtual void fly() = 0 ;
};
现在我有一个Duck类,它需要有上述2个类的瞬间。我在做的是:
class Duck
{
public:
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
Duck()
{
}
virtual void display() = 0 ;
void performQuack()
{
quackBehavior.quack() ;
}
void performFly()
{
flyBehavior.fly() ;
}
void swim()
{
std::cout << "All ducks swim!\n" ;
}
};
我还创建了实现接口的类:
class Quack: public QuackBehavior
{
void quack()
{
std::cout << "QUACK!\n" ;
}
};
class FlyWithWings: public FlyBehavior
{
void fly()
{
std::cout << "I'm flying...\n" ;
}
};
同样如此。我创建了一个继承Duck类和我的main方法的类:
class MallardDuck: public Duck
{
public:
MallardDuck()
{
quackBehavior = new Quack() ;
flyBehavior = new FlyWithWings() ;
}
void display()
{
std::cout << "I'm a real duck\n" ;
}
};
int main(int argc, char const *argv[])
{
Duck mallard = new MallardDuck() ;
mallard.performFly() ;
mallard.performQuack() ;
return 0;
}
然而,当我编译程序时,我得到了一长串错误。有人可以帮我弄这个吗?提前感谢那些真正阅读完整问题的人。
答案 0 :(得分:2)
FlyBehavior/QuackBehavior
是抽象类,你不能使它们成为Duck
的成员,你必须使用指针代替(动态多态性通过引用或指针调度):
#include <memory>
class Duck
{
public:
std::unique<FlyBehavior> flyBehavior;
std::unique<QuackBehavior> quackBehavior;
//...
};
MallardDuck() : flyBehavior( new FlyWithWings()), quackBehavior(new Quack())
{ }
由于FlyBehavior/QuackBehavior
用作抽象类,因此您应该将它们的析构函数设置为虚拟。
class QuackBehavior
{
public:
virtual void quack() = 0 ;
virutal ~QuackBehavior() {}
};
class FlyBehavior
{
public:
virtual void fly() = 0 ;
virtual ~FlyBehavior() {}
};
答案 1 :(得分:1)
您不能拥有抽象类的实例。您应该有指向基类的指针,而不是Duck
中的对象,否则您将收到编译错误。
这一点也很明显:
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
new Quack()
和new FlyWithWings()
都返回指针。
答案 2 :(得分:1)
不要忘记实现纯虚方法:
virtual void quack() = 0 ;
正常声明对象时,不能new
它。当你将它声明为指针时,你必须通过->
调用它的项目。
QuackBehavior quackBehavior;
quackBehavior = new Quack() ; // <------- ERROR, quackBehavior is not a pointer
和
Duck mallard = new MallardDuck(); // <------- ERROR, mallard is not a pointer
mallard.performFly() ; // <-------- ERROR, you must use -> instead of .
// if mallard is a pointer
最后,使用此代码:
class MallardDuck: public Duck
{
public:
MallardDuck()
{
}
void display()
{
std::cout << "I'm a real duck\n" ;
}
};
int main(int argc, char const *argv[])
{
Duck *mallard = new MallardDuck() ;
mallard->performFly() ;
mallard->performQuack() ;
...
delete mallard;
}
你正在学习C ++,在理解指针之后,最好知道并使用智能指针(std::unique_ptr
,std::shared_ptr
)而不是简单的指针。
答案 3 :(得分:1)
在类Duck
中,抽象类成员对象flyBehavior
和quackBehavior
需要在构造函数中使用派生类FlyWithWings
和Quack
进行实例化,同时成员需要是使用这种继承方案的类型指针:
class Duck
{
public:
FlyBehavior* flyBehavior;
QuackBehavior* quackBehavior;
Duck()
{
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
~Duck()
{
delete flyBehavior;
delete quackBehavior;
}
virtual void display() = 0 ;
void performQuack()
{
quackBehavior.quack() ;
}
void performFly()
{
flyBehavior.fly() ;
}
void swim()
{
std::cout << "All ducks swim!\n" ;
}
};
您还需要基类中的虚拟析构函数:
class QuackBehavior
{
public:
virtual void quack() = 0 ;
virtual ~QuackBehavior();
};
class FlyBehavior
{
public:
virtual void fly() = 0 ;
virtual ~FlyBehavior();
};
答案 4 :(得分:0)
通过将此函数声明为纯虚拟:
virtual void display() = 0 ;
,你正在有效地制作它所属的类,抽象。抽象意味着它永远不会被实例化。您永远不能创建抽象类类型的实例。如果你想能够拥有Duck对象,请摆脱= 0.