Допустим, у меня есть следующая иерархия классов:
class A
{
public:
virtual ~A();
};
class B : public A
{};
class AUser
{
public:
virtual ~AUser();
protected:
A* m_pA;
};
class BUser : public AUser
{};
Теперь я хочу добавить метод B
который не имеет отношения к A
и будет вызываться только из BUser
,
class B : public A
{
public:
void addedFunctionality()
{
// do something
}
};
Для вызова добавленного метода у меня есть два варианта:
Добавьте пустой метод к A:
class A
{
public:
virtual ~A();
void addedFunctionality()
{
// do nothing
}
};
class BUser : public AUser
{
void useB()
{
m_pA->addedFunctionality();
}
};
вызовите добавленный метод, используя downcast:
class BUser : public AUser
{
void useB()
{
static_cast<B*>(m_pA)->addedFunctionality();
}
};
Я знаю, что следует избегать падений, но мне не нравится первый вариант, так как он раздут A
Код без причины.
Есть ли другая альтернатива дизайна?
Самое простое решение выглядит так (также предложено Ульрих Экхардт):
class AUser
{
public:
AUser(A* a)
{
m_pA = a;
}
protected:
A* m_pA;
};
class BUser : public AUser
{
public:
BUser(B* b) : AUser(b)
{
m_pB = b;
}
void useB()
{
m_pB->addedFunctionality();
}
protected:
B* m_pB;
};
Менее чистый, но вы также можете рассмотреть это:
class BUser : public AUser
{
public:
BUser(B* b) : AUser(b)
{
}
void useB()
{
getB()->addedFunctionality();
}
protected:
B *getB()
{
return dynamic_cast<B*>(m_pA);
}
};