Это не то, для чего virtual
.
virtual
есть, чтобы включить полиморфное поведение.По сути, чтобы включить это:
struct A {virtual void foo()=0;};
// Two different "behaviors" for the same "A"
struct B {void foo() override{}};
struct C {void foo() override{}};
// forgive the leak, this is just to prove a point.
A* b = new B();
A* c = new C();
b->foo(); // Will call B::foo, even though this is a pointer to "A"
c->foo(); // Will call C::foo, even though this is a pointer to "A"
То, как вы пытаетесь его использовать, вы теряете это преимущество и просто получаете производительность виртуальных функций даром.Тот факт, что создание экземпляра класса, который не реализует какую-либо чисто виртуальную функцию, является ошибкой, просто предотвращает некорректно созданные программы.
Если вы хотите убедиться, что B
реализует некоторый интерфейс, просто используйте этот интерфейсгде-то.Если B
не реализует его, вы получите искомую ошибку компилятора:
class B {};
template<typename T> void call_foo(T* v1, T* v2) {
v1->foo(&v2);
}
B b1;
B b2;
b1.foo(&b2); // error
call_foo(&b1, &b2); // error
Затем, чтобы избавиться от ошибки, вы можете просто реализовать функцию.Нет virtual
необходимо:
class B {
void foo(B*) {/*do something*/}
};
B b1;
B b2;
b1.foo(&b2); // ok
call_foo(&b1, &b2); // ok
Но почему я не могу использовать виртуальную функцию для этого?
Представьте себе следующий сценарий:
struct A {virtual void foo(A*)=0;};
// Imagine if the language allowed this:
struct B {void foo(B*) override{}};
struct C {void foo(C*) override{}};
// (...)
// I create a vector of objects, and insert three of them in this vector.
std::vector<A*> objects;
// Note that foo is well-defined only for the first two.
objects.push_back(new B();)
objects.push_back(new B();)
objects.push_back(new C();)
// Then I shuffle the vector
std::shuffle(objects.begin(), objects.end());
// At least one of these three lines should give a compiler error.
// Which one(s)?
objects[0]->foo(objects[1]);
objects[0]->foo(objects[2]);
objects[1]->foo(objects[2]);
Но мне нужно, чтобы функция была виртуальной, и мне нужна безопасность типов!
Виртуальные функции - это механизм времени выполнения.Вам нужно будет проверить тип во время выполнения. ответ Зара уже хорошо это освещает, поэтому я не буду вдаваться в подробности.Подводя итог: просто dynamic_cast
в нужный тип, и если приведение вернет nullptr
, у вас неправильный тип.Затем вы можете сгенерировать исключение или распечатать диагностическое сообщение.