Является ли определение области допустимым способом доступа к виртуальным функциям?
У меня есть программа C++ с 4 классами: Person, Student, Employee и PartTimeStudent.
Студент и сотрудник каждый происходят от Person, а PartTimeStudent происходит от всех 3 классов (что делает его наиболее производным классом). В каждом классе есть виртуальная функция вызывается VDescribe().
Пожалуйста, смотрите код ниже:
class Person
{
...
virtual void VDescribe();
...
};
class Student : virtual public Person
{
...
virtual void VDescribe();
...
};
class Employee : virtual public Person
{
...
virtual void VDescribe();
...
};
class PartTimeStudent : virtual public Person,
virtual public Student,
virtual public Employee
{
...
virtual void VDescribe();
...
};
Примечание: В приведенном выше фрагменте кода я опустил конструкторы, деструкторы и переменные-члены, поскольку они не относятся к вопрос.
Кроме того, у меня есть следующий код, в котором создается объект PartTimeStudent и доступ к нему осуществляется с помощью указателя. Я использую scoping для вызова функций VDescribe () различных вложенных объектов в объекте PartTimeStudent.
void DoTest()
{
PartTimeStudent* pPTS = new PartTimeStudent("John", 23, "NTU", "Seven-Eleven");
pPTS->VDescribe();
pPTS->::Person::VDescribe();
pPTS->::Student::VDescribe();
pPTS->::Employee::VDescribe();
}
Код компилируется успешно, и я могу вызвать различные версии VDescribe(). Я хочу знать, является ли это законным средством доступа к виртуальным функциям? Является ли это приемлемой или обескураживающей практикой?
2 ответа:
Да, это совершенно законный способ обойти динамическую диспетчеризацию и вызвать конкретную версию виртуальной функции, а не ее конечный переопределитель.
Тем не менее, я обычно нахожу странным видеть такой код на вне класса, и я бы проверил, нет ли, возможно, проблемы с дизайном или недопонимания. Обычно такой код используется внутри самого класса для вызова переопределенной версии функции (обычно из переопределителя).
Это законный способне виртуально вызывать эти функции. Общего запрета нет, но вы должны быть осторожны, когда делаете это в конструкторах (поскольку ваши базовые классы
virtual
). Вы должны знать наверняка, что названный базовый подобъект уже существует. Для невиртуальных базовых классов это не проблема, поскольку они построены по порядку.