Наследование - проблема инстанции - PullRequest
2 голосов
/ 09 апреля 2011

В Inheritance, когда создается производный класс (создается производный класс obj), тогда первая память откладывается.После этого вызывается конструктор производного класса.

class Base
    {
    public:
        int m;   
        Base(int x=0)
            : m(x)
        {
        }
    };

    class Derived: public Base
    {
    public:
        double n;

            Derived(double y=0.0)   
            : n(y)
            {
        }
    };

В приведенном выше примере при создании объекта производного класса вызывается конструктор производного класса.

Проблема в том, что, как я изучал, конструктор базового класса вызывается до вызова конструктора производного класса.Но нигде в производном классе нет явной инструкции, чтобы сначала перейти к конструктору базового класса.Как компилятор узнает, что конструктор базового класса должен быть выполнен первым ????

Я думал, что ответом будет следующая строка в объявлении базового класса:

class Derived: public Base

Но,проблема заключается в изменении производного класса следующим образом: мы можем убедиться, что конструктор базового класса вызывается и инициализируется перед выполнением тела производного конструктора.

class Derived: public Base
    {
    public:
        double n;

            Derived(double y=0.0, int z=0)   
            : Base(z), n(y)
            {
        }
    };

Итак, проблема в том, что в первом примере не было операторачтобы сказать, что конструктор базового класса должен быть вызван первым, но на самом деле он вызывается первым, во втором измененном примере я сообщаю компилятору сначала перейти к конструктору базового класса.Разве он уже не знает, как перейти к конструктору базового класса?Какая разница в исполнении между двумя примерами и каковы этапы?

С уважением,

Ответы [ 5 ]

3 голосов
/ 09 апреля 2011

Компилятор знает, как вызвать конструктор класса Base, потому что вы указали, что наследуете Base с помощью инструкции:

class Derived : public Base

Независимо от того, что компилятор собирается создать(т.е. вызовите конструктор) базового класса перед вызовом конструктора Derived.Он также предназначен для правильного построения производного класса.

Во втором примере, где вы указываете: Base(z) в вашем списке инициализации, вы говорите компилятору явно вызывать / инициализировать базовый класс с помощью этогоконструктор.Когда вы не указываете конструктор через список инициализации, компилятор всегда вызывает конструктор по умолчанию.Указание правильного конструктора в списке инициализации (даже если он используется по умолчанию) считается наилучшей практикой.

1 голос
/ 09 апреля 2011

Если у вас есть шар и вы получаете из него красный шар, то для создания красного шара первым, что вам нужно, это шар, тогда вы можете нарисовать его красным.Полученный в вашем примере, вам нужно начать с объекта типа Base, а затем создать Derived из него.Таким образом, даже если вы явно не вызываете конструктор базового класса, компилятор знает, что это необходимо.Строка

 class Derived: public Base

фактически является инструкцией, которая сообщает компилятору об этом.

Во втором случае вы явно об этом говорите.Это может быть использовано в случае, если вы хотите вызвать конструктор базового класса, у которого есть параметры, скажем.

0 голосов
/ 09 апреля 2011

Я думаю, что заблуждение состоит в том, что язык C ++ каким-то образом интерпретируется пошагово, иначе я не могу объяснить, "если компилятор уже не вызвал конструктор базового класса и не инициализировал его, прежде чем он увидит вызов в конструктор класса ".

Это не тот случай, в основном компилятор «видит» все модули компиляции, прежде чем он начнет генерировать вывод. Если он обнаружит, что вы сделали явный вызов одному конкретному конструктору - через Base (z), в вашем случае он вызовет его при создании вашего производного объекта. В противном случае он вызовет конструктор по умолчанию для Base.

Вероятно, было бы лучше не объявлять ваш базовый конструктор как Base (int x = 0). Попробуйте создать как конструктор без параметров, так и конструктор Base (int) и поместить точку останова в каждый из них, чтобы точно определить, какой из них вызывается. (в качестве альтернативы, установите точку останова в Base (int x = 0) и проверьте значение x ...)

0 голосов
/ 09 апреля 2011

Какая разница в выполнении между двумя примерами и каковы этапы?

Разница в том, что в первом случае будет вызываться конструктор DEFAULT, а во втором - тот, который вы выбрали.

0 голосов
/ 09 апреля 2011

В первом примере вы вызываете конструктор по умолчанию. Во втором примере вы вызываете конструктор с параметром

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...