我正在编写一个我在其中使用策略的项目,但是,我的派生类还具有基类不应该具有的其他附加功能。
class Base {
public:
virtual void execute() = 0;
virtual void print() const noexcept = 0;
virtual ~Base() {}
};
class DerivedA : public virtual Base {
public:
void execute() override;
void print() const noexcept override;
void doSomething();
private:
int x;
double y;
};
class DerivedB final : public Base {
public:
void execute() override;
void print() const noexcept override;
std::string getZ() const noexcept;
private:
std::string z;
};
在main()中,我试图使用dynamic_cast来使用以下附加功能:
int main() {
DerivedA da;
Base* base = &da;
DerivedA* derivedA = dynamic_cast<DerivedA*>(base);
derivedA.doSomething();
return 0;
}
但是,当我尝试运行代码时,出现以下错误:
“ DerivedA *”的间接级别与“ DerivedA”
不同
我的问题是,我是否应该为此使用策略,还是应该使用其他设计模式?如果我应该使用策略,该如何解决这个错误?
更新
我正在考虑切换到装饰器,因为DerivedA可以是DerivedB的基类,但是,我担心转换,因为每个类都有不同的类成员。
更新
似乎我写错了演员表。但是,我在这里张贴时写的正确!现在可以使用,但是,我同意,有一种更好的方法可以实现这一点。
答案 0 :(得分:2)
如果这正是您要编译的代码,则解决方案很容易。代替
derivedA.doSomething();
您应该写
derivedA->doSomething();
由于派生的是指针,而不是引用或实例。
但是,对于考虑dynamic_cast
,我还有其他一些严重的担忧。我的意见是,如果您使用dynamic_cast
,则可能是您的设计有问题。您有一个隐藏实现的接口,但有一些代码依赖于实现而不是在接口中。
要考虑的一些替代方法:
IAnimal
,并且您的某些动物可以游泳,请创建一个界面ISwimmable
,然后向IAnimal
添加一个方法,该方法返回指向ISwimmable
的指针({{ 1}})。可以游泳的动物实现可以从IAnimal::getSwimmable
继承并实现ISwimmable
并返回指向getSwimmable
接口的指针(因此,实际上返回其自身,这只是隐式本身)。不会游泳的动物可以返回ISwimmable
(如果您想保留接口a,它可能是nullptr
中的默认实现,或者是从IAnimal
继承的某些AnimalBase
类纯接口)。 Microsoft的COM系统还使用了第二种方法,其中每个COM接口都实现了IAnimal
接口,并且您可以调用IUnknown
来获取特定的不同接口以实现某些“功能”。
答案 1 :(得分:1)
在iw工作文件下面的代码为我提供了g ++和编译功能: g ++ main.cc -o main -std = c ++ 14
#include <string>
class Base {
public:
virtual void execute() = 0;
virtual void print() const noexcept = 0;
virtual ~Base() {}
};
class DerivedA : public virtual Base {
public:
void execute() override {}
void print() const noexcept override {}
void doSomething(){}
private:
int x;
double y;
};
class DerivedB final : public Base {
public:
void execute() override {}
void print() const noexcept override {}
std::string getZ() const noexcept {}
private:
std::string z;
};
int main() {
DerivedA da;
Base* base = &da;
DerivedA* derivedA = dynamic_cast<DerivedA*>(base);
derivedA->doSomething();
return 0;
}
答案 2 :(得分:1)
您所描述的是软件中的一个常见问题,并且在各种设计模式中都出现了很多问题。您想多态使用DerivedA
和DerivedB
,因此它们必须共享一个公共接口。没关系。但是,DerivedA
有一个您也想使用的有用方法doSomething
。您可以选择以下两种方式:
doSomething
方法,这会使您的代码保持整洁; doSomething
,但是您的代码不可避免地看起来有些hacky; doSomething
中执行Base
不执行任何操作,那么代码看起来不错,但是当您在doSomething
引用上调用Base
时,如果接收到对象实际上是类DerivedB
中的对象。装饰器在这里并没有真正的帮助。装饰器非常适合扩充现有方法。如我所知,您不能使用它(以静态类型的语言)添加新方法:-)