问题
I know that virtual functions should not be called either directly or indirectly in a constructor, but this code runs fine.
Is what I have here safe?
#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"
}
If not, would the following (based on a comment) be a correct workaround?
// 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
};
回答1:
Invoking virtual members in the constructor and/or destructor is generally ok.
It's a different game in the ctor initializer though, before all bases are initialized:
12.6.2 Initializing bases and members
[class.base.init][...]
14 Member functions (including virtual member functions, 10.3) can be called for an object under construction. Similarly, an object under construction can be the operand of thetypeidoperator (5.2.8) or of adynamic_cast(5.2.7). However, if these operations are performed in a ctor-initializer (or in a function called directly or indirectly from a ctor-initializer) before all the mem-initializers for base classes have completed, the result of the operation is undefined.
来源:https://stackoverflow.com/questions/25754796/may-i-call-a-virtual-function-to-initialize-a-base-class-sub-object