Я озадачен поведением ниже, что я не могу объяснить.Я пытался написать содержательное название, но я не уверен, что прибил это.
Сначала немного фона.Я пишу программное обеспечение для численного моделирования и пытаюсь немного модернизировать свой код.У меня есть три числовых решателя: primal
, dual
и adaptive
.primal
решатель делает свою работу, ничего не зная;решатель dual
имеет много общего с primal
, но никогда не используется отдельно, а решатель adaptive
- это оболочка, которая содержит и запускает primal
и dual
в этом порядке.Дело в том, что когда решатель adaptive
запускает свой решатель primal
, primal
необходимо выполнить некоторые дополнительные операции по сравнению с тем, когда он используется один.Пусть одна такая операция будет save
.Кроме того, primal
и dual
имеют много общего, поэтому я решил, что они должны совместно использовать код в классе common
.
Это был мой первоначальный дизайн
#include <iostream>
using namespace std;
template <typename s>
struct common
{
void run()
{
static_cast<s*>(this)->save();
}
};
struct primal : public common<primal>
{
virtual void save()
{
cout << " Primal\n";
}
};
struct dual : public common<dual>
{
void save()
{
cout << " Dual\n";
}
};
struct adaptive : public primal,
public dual
{
void run()
{
primal::run();
dual::run();
}
virtual void save()
{
primal::save();
cout << " Adaptive\n";
}
};
int main(int argc, const char *argv[])
{
adaptive a;
a.run();
return 0;
}
, и этопечатает
Primal
Adaptive
Dual
, что для меня означает, что
a.run
вызывает primal::run = common<primal>::run
common<primal>::run
вызывает primal::save
, но этот методэто virtual
, поэтому он разрешает вызов adaptive::save
adaptive::save
вызовов primal::save
явно, потому что я хочу, чтобы он выполнял обычные задачи primal
плюс что-то еще adaptive::save
выполняет какую-то другую работу и возвращает a.run
, вызывает dual::run = common<dual>::run
, что вызывает dual::save
, но этот метод не virtual
, поэтому он выбран без учета adaptive::save
.
Пока все хорошо, и это именно то, что я хотел.Итак, первый вопрос: верно ли все вышесказанное?
Теперь вот и проблемы.После некоторого рефакторинга primal::save
и dual::save
теперь являются одной и той же функцией, поэтому я хочу поместить ее в common
и продолжать расширять поведение только в adaptive
.
В качестве первого шага яизменил код на
template <typename s>
struct common
{
void run()
{
save();
}
virtual void save()
{
cout << "This should never be called\n";
}
};
// Everything else stays the same
и теперь вывод равен
Primal
Adaptive
Primal
Adaptive
, в то время как я ожидал того же вывода, что и раньше.Это первое, что я не понимаю: мне кажется, что теперь вызов dual::save
, сделанный dual::run()
, разрешается вплоть до adaptive::save
, в то время как я ожидал, что он остановится на dual::save
, так какэтот метод не virtual
.Это мой второй вопрос: почему это происходит?Чем отличается от ранее?
Наконец, я написал код, который я имел в виду в его окончательной версии, плюс некоторые вещи для отладки, и он выглядит так:
#include <iostream>
using namespace std;
template <typename s>
struct common
{
void run()
{
save();
}
virtual void save()
{
cout << s::name << "::common\n";
}
};
struct primal : public common<primal>
{
static const string name;
};
const string primal::name = "primal";
struct dual : public common<dual>
{
static const string name;
};
const string dual::name = "dual";
struct adaptive : public primal,
public dual
{
virtual void save()
{
primal::save();
cout << " Adaptive\n";
}
void run()
{
primal::run();
dual::run();
}
};
int main(int argc, const char *argv[])
{
adaptive a;
a.run();
return 0;
}
ион печатает
primal::common
Adaptive
primal::common
Adaptive
как предыдущая версия, тогда как я ожидал
primal::common
Adaptive
dual::common
Последний вопрос заключается в том, как заставить его делать то, что я хочу.
Спасибо за то, что прочитали все до конца, любая подсказка приветствуется!Я должен придерживаться C ++ 98, если это возможно.