Могу ли я вызвать виртуальную функцию для инициализации подобъекта базового класса?

Я знаю, что виртуальные функции не должны вызываться ни прямо, ни косвенно в конструкторе, но этот код работает нормально.
Что у меня здесь безопасно?

#include <iostream>
#include <string>

struct A {
A (const std::string& name) {std::cout << name << std::endl;}
virtual std::string tag() const = 0;
};

struct B: A {
B() : A (tag()) {}
virtual std::string tag() const override {return "B";}
};

int main() {
B b; // Output gives "B\n"}

Если нет, то будет ли следующее (на основе комментариев) правильным решением?

// Replacement for class B:

struct B: A {
B() : A (name()) {}
virtual std::string tag() const override {return name();}
private:
static std::string name() {return "B";}  // use static function
};

2

Решение

Вызывать виртуальные члены в конструкторе и / или деструкторе обычно нормально.

Это другая игра в инициализаторе ctor, хотя до инициализации всех баз:

12.6.2 Инициализация баз и членов [class.base.init]

[…] 14 Функции-члены (включая виртуальные функции-члены, 10.3) могут быть вызваны для строящегося объекта.
Точно так же строящийся объект может быть операндом typeid оператор (5.2.8) или dynamic_cast (5.2.7). Однако, если эти операции выполняются в т е р-инициализатор (или в функции, вызываемой прямо или косвенно из инициализатора ctor) до завершения всех инициализаторов mem для базовых классов результат операции не определен.

5

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