Вы не можете переопределить их по отдельности, вы должны переопределить оба сразу:
struct Interface1 {
virtual void Name() = 0;
};
struct Interface2 {
virtual void Name() = 0;
};
struct RealClass : Interface1, Interface2 {
virtual void Name();
};
// and move it out of the class definition just like any other method:
void RealClass::Name() {
printf("Interface1 OK?\n");
printf("Interface2 OK?\n");
}
Вы можете моделировать индивидуальное переопределение с помощью промежуточных базовых классов:
struct RealClass1 : Interface1 {
virtual void Name() {
printf("Interface1 OK?\n");
}
};
struct RealClass2 : Interface2 {
virtual void Name() {
printf("Interface2 OK?\n");
}
};
struct RealClass : RealClass1, RealClass2 {
virtual void Name() {
// you must still decide what to do here, which is likely calling both:
RealClass1::Name();
RealClass2::Name();
// or doing something else entirely
// but note: this is the function which will be called in all cases
// of *virtual dispatch* (for instances of this class), as it is the
// final overrider, the above separate definition is merely
// code-organization convenience
}
};
Кроме того, вы используете reinterpret_cast неправильно, вы должны иметь:
int main() {
RealClass rc; // no need for dynamic allocation in this example
Interface1& one = rc;
one.Name();
Interface2& two = dynamic_cast<Interface2&>(one);
two.Name();
return 0;
}
А вот переписать с CRTP , который может быть тем, что вы хотите (или нет):
template<class Derived>
struct RealClass1 : Interface1 {
#define self (*static_cast<Derived*>(this))
virtual void Name() {
printf("Interface1 for %s\n", self.name.c_str());
}
#undef self
};
template<class Derived>
struct RealClass2 : Interface2 {
#define self (*static_cast<Derived*>(this))
virtual void Name() {
printf("Interface2 for %s\n", self.name.c_str());
}
#undef self
};
struct RealClass : RealClass1<RealClass>, RealClass2<RealClass> {
std::string name;
RealClass() : name("real code would have members you need to access") {}
};
Но учтите, что здесь вы не можете вызывать Name в RealClass сейчас (при виртуальной диспетчеризации, например, rc.Name()
), вы должны сначала выбрать базу. Сам макрос является простым способом очистки приведений CRTP (как правило, доступ к элементам гораздо более распространен в базе CRTP), но он может быть улучшен . В одном из моих других ответов есть краткое обсуждение виртуальной рассылки, но, конечно, лучше, если у кого-то есть ссылка.