在设计建筑时偶然发现了一个噱头。我有一个抽象类Model和两个后代 - Model1和Model2。Model1有一个int(a)类型的成员,而Model2 有一个const char (b)*。还有一个抽象类Render和两个后代 - Render1和Render2。Render提供了一个纯虚成员函数draw,它接受 *Model** 类型。现在,在Render1类中,在draw方法中,我执行了一些操作,我需要访问成员a, 类Model1。反过来,在Render2类中也需要访问Model2类的成员b。按照设计,Model1类不能传递给Render2类,反之亦然。在这种情况下如何行动?使用多态的基本代码如下所示:
class Model
{
public:
virtual void init() = 0;
};
class Model1 : public Model
{
int a;
public:
void init() override
{
a = 48;
}
};
class Model2 : public Model
{
const char* b;
public:
void init() override
{
b = "test";
}
};
class Render
{
public:
virtual void draw(Model* m) = 0;
};
class Render1: public Render
{
public:
void draw(Model* m) override
{
// здесь сделать что - то с a
}
};
class Render2 : public Render
{
public:
void draw(Model* m) override
{
// здесь сделать что - то с b
}
};
PS:我知道Renders不应该知道谁来找他们(类的哪个实例),但我想不出更好的办法。请告知在这种情况下如何进行。使用多态和继承是因为类太通用了。PSS:我知道 dynamic_cast,但它也破坏了架构,我试图避免它
UPD1: 当使用访问者时,我想分离继承人的能力,因为在使用一个访问者的情况下,许多库是连接的。我想要某个标题中的某个库。换句话说,是否可以这样做:
class Foo;
class Bar;
class Visitor
{
public:
virtual void visit(Foo &ref) = 0;
virtual void visit(Bar &ref) = 0;
virtual ~Visitor() = default;
};
class GetType : public Visitor
{
public:
std::string value;
public:
void visit(Foo &ref) override
{
value = "Foo";
}
void visit(Bar &ref) override
{
value = "Bar";
}
};
像这样:
class Foo;
class Bar;
class Visitor
{
public:
virtual void visit(Foo& ref) = 0;
virtual void visit(Bar& ref) = 0;
virtual ~Visitor() = default;
};
class GetTypeFoo : public Visitor
{
public:
std::string value;
public:
void visit(Foo& ref) override
{
value = "Foo";
}
void visit(Bar& ref) override
{
// empty
}
};
class GetTypeBar : public Visitor
{
public:
std::string value;
public:
void visit(Foo& ref) override
{
// empty
}
void visit(Bar& ref) override
{
value = "Bar";
}
};
好吧,正确的方法将分别在正确的时间被调用。
在您的情况下,像访问者这样的编程模式是完美的。Tobish在您传递对象
draw
的基类中创建一个虚函数。所以你摆脱了确定类型的问题,因为对象先验地知道它是什么类型。Model
Render
因此,您将拥有两种基本类型:一种用于
visitor
-s,第二种用于接受访问者的对象。派生(来自基类)访问者的数量没有限制,但请记住,如果添加接收访问者的新类,则必须确保所有访问者都支持新类!这会产生一些复杂性,但是如果某些访问者(或除一个之外的所有访问者)不应该对新类型的对象执行任何操作,那么为了简化实现,visitor
所有函数都可以在基类中定义,而不是抽象的,而是使用空执行。