C ++ наследование: определить унаследованные методы во время выполнения

У меня есть класс D, который расширяет B, который расширяет A. Теперь я хочу добавить класс C, который имеет точно такой же интерфейс, что и B, но обеспечивает другую реализацию. Поэтому я спроектировал это следующим образом:
бриллиант

Это не совсем то, что я хочу, так как мне нужен только экземпляр D для расширения B или C, а не оба, однако, это определяется только во время выполнения. Проблема с дизайном выше состоит в том, что если я вызываю метод в D, который реализован как в B, так и в C, то он неоднозначен.

Поэтому я хотел бы создать экземпляр B или C во время выполнения и затем преобразовать его в D. Каждый раз, когда экземпляр D вызывает унаследованный метод, он должен использовать тот из своего исходного объекта.

Нужно ли возиться с typeid и if / else вокруг каждого вызова метода или есть более элегантный способ сделать это?

class A{
virtual f1();
virtual f2();
}

class B : public virtual A{
f1();
f2();
f3();
}

class C : public virtual A{
f1();
f2();
f3();
}

class D : public B, public C{
f4(){f1(); f3)};
}

...
D* d = new D();
E* e = new E(d);
e->d->f1();
e->d->f4();

Экземпляры D затем передаются другому классу (E), который работает с D, и поэтому я не могу изменить интерфейс D.

0

Решение

Я думаю, что у вас неправильное наследование, то, что вы делаете, это определяете все методы, которые вы хотите вызывать для того, что вы называете классом D, как виртуальные методы в классе A, классы B и C оба имеют свою собственную реализацию этих методов. ,

Затем вы используете структуру данных типа A *, заполняете ее указателями на объекты типа B и C и вызываете методы, которые вам нужно вызывать для всех объектов в структуре данных, содержащей указатели типа A *, vtable Затем механизм убедится, что реализация класса B или C используется в зависимости от того, какой тип объекта является действительным.

Увидеть В чем разница между конкретным классом и абстрактным классом?

2

Другие решения

Похоже, вы просто хотите

class A{
virtual void DoMagic() = 0;

};
class B{
virtual void DoMagic(){};

};
class D{
virtual void DoMagic(){};

};

...
bool INeedB = true;//or false
A* a;
if(INeedB){
a= new B();
}else{
a = new C();
}
a->DoMagic(); // will call the appropriate method based on the value of INeedB;

Разве D на самом деле имеет собственное поведение? Тогда вы можете посмотреть на шаблон декоратора, и сделать D декоратором экземпляра B или C.

Редактировать: Ваш D класс не должен наследовать какой-либо из A B или же C совсем.

class D{
D(A* aObj):a(aObj){}
void f3(){ a->f1();a->f2();}
A *a;
};

замещать A *a в приведенном выше примере с D d

1

C ++ — это статически типизированный язык. Что бы вы ни делали с объявлением типа, оно разрабатывается во время компиляции, поэтому граф наследования D нельзя игнорировать во время выполнения.

Вам, вероятно, нужно иметь A как полиморфная база (со всеми соответствующими виртуальными методами, включая деструктор) как для B, так и для C (конкретная реализация этого), и D an «владелец A«, содержащая A * thet будет назначена в конструкции D для new B или же new C в зависимости от ввода.

Д деструктор позвоню delete A, и теперь вы должны принять решение о копировании и назначении.

Мое предложение не использовать A *, а std::unique_ptr (сделает принадлежащий объект подвижным между D-s) или std::shared_ptr,

В случае, если вам нужно, чтобы у каждого D была своя собственная A, пусть A имеет clone метод (переопределяется в B и C, чтобы вернуть new B а также new C соответственно) и назовите его в экземпляре d ctor и операторе присвоения.

0

Это похоже на D не нужно наследовать от A (или же B или же C) совсем. Вместо этого ему просто нужно вызвать функцию в любом случае B или экземпляр C,

Вы можете реализовать это примерно так:

class A
{
public:
virtual void f1();
virtual void f2();
};

class B : public A;
class C : public A;

class D
{
A* b_or_c;

public:
D(A* a_pointer)
: b_or_c(a_pointer)
{}

void f3()
{
b_or_c->f1();
b_or_c->f2();
}
};

Можно использовать так:

B b;  // An instance of B
C c;  // An instance of C

D d1(&b);
D d2(&c);

d1.f3();  // Will cause `f1` and `f2` in the object `b` to be called
d2.f3();  // Will cause `f1` and `f2` in the object `c` to be called
-1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector