Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 面向对象的多态处理设计_C++_Oop_Design Patterns_Polymorphism - Fatal编程技术网

C++ 面向对象的多态处理设计

C++ 面向对象的多态处理设计,c++,oop,design-patterns,polymorphism,C++,Oop,Design Patterns,Polymorphism,我有从一个基础派生的不同类型的对象(例如圆、矩形、多边形…等等),我有一组预定义的操作,可以应用于这些对象(例如移动、旋转、复制…等等)。 在这种情况下,我喜欢的解决方案是访问者模式。我的每一个操作都有访客,包含所有类型的全套操作。这允许我在不改变对象本身的情况下向对象添加新函数。操作肯定会比新的对象类型更频繁地更改和添加,所以这真的很好,但有一个问题。 上述所有内容都是作为一个库实现的,将来可能(并且将)由其他程序员扩展。程序员可以添加新类型的对象,或者实现操作,或者不实现操作。例如,可以添加

我有从一个基础派生的不同类型的对象(例如圆、矩形、多边形…等等),我有一组预定义的操作,可以应用于这些对象(例如移动、旋转、复制…等等)。 在这种情况下,我喜欢的解决方案是访问者模式。我的每一个操作都有访客,包含所有类型的全套操作。这允许我在不改变对象本身的情况下向对象添加新函数。操作肯定会比新的对象类型更频繁地更改和添加,所以这真的很好,但有一个问题。 上述所有内容都是作为一个库实现的,将来可能(并且将)由其他程序员扩展。程序员可以添加新类型的对象,或者实现操作,或者不实现操作。例如,可以添加支持移动但不支持旋转的“三角形”类。在这种情况下,程序员将无法扩展我的访问者来处理其对象的移动操作。 我看到了另一个解决方案——拥有像I_可移动、I_可旋转、I_可复制这样的接口。每个类实现一个或多个接口,然后我在我的库中进行检查,如果指定的对象支持使用dynamic_cast的给定接口,并应用该操作。差不多

if (i_movable* m = dynamic_cast<i_movable>(obj)) m->move(10, 20);
if(i_movable*m=dynamic_cast(obj))m->move(10,20);
但我不太喜欢这个解决方案。有人能提出更好的建议吗

这可能不是面向对象设计的重要因素,但是实现的语言是C++,所以我受限于C++的能力。 更新

如果没有人能想出更好的解决方案,请您至少为提议的解决方案留一票好吗

提前感谢。

而不是:

if (i_movable* m = dynamic_cast<i_movable>(obj)) m->move(10, 20);
if(i_movable*m=dynamic_cast(obj))m->move(10,20);
您可以使用一些模板元编程技巧(了解一下):

#包括“boost/type\u traits/is\u base\u of.hpp”
#包括
结构i_移动
{
虚空移动(常量浮点,常量浮点)=0;
};
结构三角形
{
//不能移动
};
结构圆:我移动
{
虚空移动(常量浮点,常量浮点)
{
//感动我
}
};
模板
布尔可压缩(D&)
{
return boost::是::value的_base_;
}
int main()
{
圈a;
三角形b;

std::cout如果我理解正确,如果操作不受支持,您什么也不做(或者更一般地说,具有独立于所讨论对象的统一行为)。然后一个简单的解决方案是在基类中提供默认行为,然后如果派生类没有实现自己的版本,则默认行为将自动生效,而无需任何额外的机制


如果我没记错的话,在Borland的Turbo Vision中,这些方法被称为“伪抽象”:它们并不是真正抽象的(不允许调用它们,也不需要在派生类中重写它们),但除非被重写,否则它们什么也不做。

您在这里描述的接口基本上就是COM的工作原理。您能描述一下“我不喜欢这个”吗部分?你在哪一部分被C++限制了?就我所见,你回答了你自己的问题。是的,它类似于COM。我不喜欢把所有函数都放在一个类中。例如,我必须在三角形类本身中实现对三角形的复制序列化、移动、旋转和其他所有操作。非常大而且很难支持(有很多不同的操作)我也尽量避免在可能的地方进行转换。我不说我不会去解决这个问题,我只是想知道是否有更好的东西。关于C++的限制:我不是说我有一些好的解决方案,但是我被C++所限制。只是提到不要混淆别人,不要让他们提出不能解决的办法。我可以同意C++,我同意你的观点,但是你能编写一些序列化、移动、旋转和其他需要的操作的通用代码吗?嗯,我可以为一些操作编写通用代码,但不是为其他操作编写通用代码。例如,我可以编写“代码>移动< /COD>函数,它将适用于一组几何结构,但是我不能编写一般的Seria。用于复制和保存对象的函数。函数模板
IsMovable
不应该只有一个类型参数吗?表示可移动性的基类的类型应该始终相同,对吗?所有这些对象都来自一个基类(比如几何体)你处理的是基类指针,所以我不能用这种方式实现它,我们这里需要动态转换。是的。你说得对,但正如我已经说过的,大约有50个不同的操作,我不想把它们都放在一个基类中。我不想在一个类中包含太多的函数。
#include "boost/type_traits/is_base_of.hpp" 
#include <iostream>

struct i_move
{
    virtual void move(const float, const float ) = 0;
};
struct Triangle
{
    // not movable
};
struct Circle : i_move
{
    virtual void move(const float, const float )
    {
        // move me
    }
};

template< class D >
bool IsMovable( D&)
{
    return boost::is_base_of<i_move,D>::value;
}

int main()
{
    Circle a;
    Triangle b;
    std::cout<<std::boolalpha<<IsMovable(a)<<std::endl;
    std::cout<<std::boolalpha<<IsMovable(b)<<std::endl;
}