#c #c 17
#c #c 17
Вопрос:
Я довольно новичок в c и учусь писать чистый код. Я хочу переписать функцию manage() в классах derived1mngr и derived2mngr ниже. Код является общим для обеих функций, единственное отличие заключается в objectytype, используемом для вызова кода. Я не хочу копировать один и тот же код в derived1mngr и derived2mngr. Любые предложения помогут? Как я могу сгруппировать код вместе в базовом классе manage?
class Base{
public:
virtual void handle(){
cout<< "handle base";
....//do something
}
void fn1() {...}
.....
void fn10() {...}
};
class D1: public Base{
public:
void handle(){
Base::handle();
cout<< "D1 handle";
....//do something
}
};
class D2: public Base{
public:
void handle(){
Base::handle();
cout<< "D2 handle";
....//do something
}
};
class basemngr {
public:
virtual void manage() {
}
void callA() {....};
void callB() {...};
};
class derived1mngr: public basemgr{
public:
void manage() {
D1 d1;
d1.handle();
d1.fn1();
d1.fn2();
if ( d1.fn3()) {
callA();
}
if ( d1.fn4()) {
callB();
}
}
};
class derived2mgr{
public:
void manage() {
D2 d2;
d2.handle();
d2.fn1();
d2.fn2();
if ( d3.fn3()) {
callA();
}
if ( d2.fn4()) {
callB();
}
}
};
int main ()
{
basemgr* d1m = new derived1mgr();
d1m-> manage();
}
Комментарии:
1. Я не понимаю смысла derivedXmgrs, поскольку каждый интерфейс реализован в basemgrs. Почему бы просто не использовать basemgrs и не принять базовый параметр. Есть ли какая-либо причина, по которой вам нужно разрешить классу mgr создавать экземпляр объекта?
Ответ №1:
Возможно, что-то в этом роде:
class basemngr {
public:
virtual void manage() {
}
void manageImpl(Baseamp; b) {
b.handle();
b.fn1();
b.fn2();
// ...
}
void callA() {....};
void callB() {...};
};
class derived1mngr: public basemgr{
public:
void manage() {
D1 d1;
manageImpl(d1);
}
};
Комментарии:
1. Tadetnik b.handle() — это виртуальный вызов.
2. @новичок И …? Каким образом этот факт влияет на предлагаемое решение, по вашему мнению?
Ответ №2:
Вообще говоря, наследование с виртуальными функциями не предназначено для повторного использования кода. Шаблоны есть.
Этот случай требует шаблона, потому что, как вы указали, функции одинаковы, за исключением используемого типа.
template <typename D, typename M>
inline void manage(Mamp; mngr) {
D d;
d.handle();
d.fn1();
d.fn2();
if (d1.fn3()) {
mngr.callA();
}
if (d.fn4()) {
mngr.callB();
}
}
Затем эта бесплатная функция может быть вызвана следующим образом:
derived2mgr mngr;
manage<D2>(mngr);
Обратите внимание, что вы можете улучшить это, указав D
тип, который хочет использовать каждый класс:
class MyMngr {
public:
using D = D3;
/* ... */
};
Что позволило бы нам переписать функцию и устранить необходимость указывать, какой D
тип использовать явно -> Меньше шансов совершить ошибку.
template <typename M>
inline void manage(Mamp; mngr) {
typename M::D d;
// ...
}