2011-01-26 11 views
5

Pytanie 1)konstruktora C++ Baza wywołanie z parametrem, który zostanie zbudowany w konstruktora pochodzącego

class Base { 
    Base(std::string name); 

    virtual std::string generateName(); 
} 

class Derived : Base { 
    Derived(); 

    virtual std::string generateName(); 
} 

tu pojawia się pytanie:

jaka metoda zostanie wywołana na generateName()?

Derived :: Derived : Base(generateName()) { 
    //what method will be called on generateName() ? 
} 

PYTANIE 2)

jak mam to zrobić? jeśli domyślny konstruktor musi zaakceptować parametr, ale muszę wygenerować ten parametr w konstruktorze pochodnym?

Odpowiedz

8

Po pierwsze, rozwiązanie: użyj statycznej funkcji składowej lub funkcji nie należącej do grupy.

Jeśli chodzi o zachowanie, zostanie wywołany Derived::generateName(). Długie zdanie w C++ Standard, które definiuje to zachowanie, mówi (C++ 03 12,7/3):

Gdy funkcja wirtualna jest wywoływana bezpośrednio lub pośrednio z konstruktora (w tym z inicjalizatora pamięci dla danych element) lub z destruktora, a obiektem, do którego odnosi się wywołanie, jest obiekt w trakcie budowy lub destrukcji, funkcja o nazwie jest zdefiniowana w klasie konstruktora lub w jednej z jego podstaw, ale nie nadpisuje funkcji to w klasie wyprowadzonej z klasy konstruktora lub destruktora lub przesłonięcie jej w jednej z innych klas bazowych obiektu najbardziej pochodnego.

Ponieważ konstruktor wykonywane w czasie rozmowy jest wirtualny konstruktor Derived, Derived::generateName() nazywa.

Obecnie usunięta odpowiedź słusznie odsyła do artykułu Scotta Meyersa, który zaleca "Never Call Virtual Functions during Construction or Destruction." Zasady nadawania nazwiskom nadzy są skomplikowane i trudne do zapamiętania.

+3

Byłoby to prawdą, gdyby 'generateName()' było wywoływane z * wewnątrz * 'Base :: Base'. Ale tutaj wywołujemy go na liście inicjalizacyjnej, zanim wejdziemy do 'Base :: Base'. Czy to nadal prawda? –

+0

Ach, zaktualizowałeś swoją odpowiedź. Czuje się teraz, więc +1. –

+1

@Oli: Nie. Myliłem się i poprawiłem odpowiedź po zbadaniu problemu i wykonaniu niektórych testów. Jestem nieco zaskoczony określonym zachowaniem. Czuję się niesłusznie ;-) (Łamie model, który generalnie stosowałem do wywoływania wirtualnych wywołań funkcji podczas budowy i teraz muszę wrócić i znaleźć wszystkie odpowiedzi, w których źle opisałem proces. .) Dziękujemy za przesłuchanie oryginalnej odpowiedzi. –

1

trwać dwa ...

Zrobiłem bieg z połączeń do generateName() w klasie bazowej initialiser i obu konstruktorów. Wyjście zostawiła mnie skonsternowany:

Derived (called from Derived's Base initializer) 
Base (called from Base ctor) 
Derived (called from Derived ctor) 

Nigdy nie wyobrażałem sobie, że klasa mogła morph od bycia wywodzi się zasadą, a następnie z powrotem do pochodzić w pojedynczej sekwencji budowlanej. Każdego dnia uczysz się czegoś nowego.

Powiązane problemy