Попытка использовать виртуальную функцию в моем списке инициализации - PullRequest
0 голосов
/ 16 марта 2020

Я пытаюсь создать базовый и производный класс с константным членом, который должен быть инициализирован:

class baseClan
{
public:
    baseClan(const string firstName)
    :
    fullName(createFullName(firstName))
    {}
private:
    const string lastName = "Smith";
    const string fullName;
    virtual const string createFullName(string firstName) { return firstName + " " + lastName ; }
}

Как реализовать производный класс, чтобы он мог использовать реализованный по-другому createFullName? Я смотрю на эту ссылку https://isocpp.org/wiki/faq/strange-inheritance#calling -virtuals-from-ctor-idiom , но кажется, что я застрял между молотом и наковальней: первый предложенный подход (с использованием init) не применимо к списку инициализации; в то время как во втором подходе прямо указано, что он не может обработать случай, когда нам нужен доступ к данным экземпляра, объявленным в Derived.

1 Ответ

0 голосов
/ 16 марта 2020

Вызывать виртуальные функции из конструктора или деструктора опасно, и его следует по возможности избегать. Все реализации C ++ должны вызывать версию функции, определенной на уровне иерархии в текущем конструкторе, и не более того.

Виртуальные функции в конструкторах работают по-разному. При создании объекта производного класса сначала создается объект базового класса, что означает, что производный класс еще не создан, а виртуальная функция еще не переопределена.

Я думаю, что все возможные подходы к этой проблеме уже описаны по указанной вами ссылке ( C ++ FAQ ). Но я настоятельно рекомендую переосмыслить ваш код.

Вы можете применить немного другой подход. Вы можете заставить базовый конструктор принимать параметры для инициализации полей данных, а затем в производном классе передать необходимые аргументы (даже, возможно, из виртуальных функций) базовому конструктору, используя список инициализации. Например:

class A {
public:
    A(int a, int b) : a_(a), b_(b) { }
    virtual int getA() const = 0;
    virtual int getB() const = 0;
    void print() { cout << a_ << ' ' << b_ << endl; }
private:
    const int a_ = 0;
    const int b_ = 0;
};

class B : public A {
public:
    B() : A(getA(), getB()) { }
    int getA() const override { return 1; }
    int getB() const override { return 2; }
};

int main() {
    B b;
    b.print();
    return 0;
}
...