Использование другого базового конструктора для производного класса C ++ - PullRequest
0 голосов
/ 15 августа 2011

Насколько я понимаю, следующий код будет выполняться в следующем порядке:

  1. Вызывается производный конструктор.
  2. Базовый объект создается с использованием базового конструктора по умолчанию.
  3. Тело производного конструктора выполняется.

Если это так, не присваивается ли члену z значение дважды?

class base {
public:
    int x, y, z;
    base() {x = 0; y = 0; z = 0;};
};

class derived : public base {
public:
    derived() {z = 5;};
};

Существует ли более эффективный способ созданияобъект класса «производный», поэтому он использует другой конструктор, в данном случае тот, который будет присваивать членам только значения x и ya, в результате чего z будет присвоено значение в производной ()?

Ответы [ 5 ]

3 голосов
/ 15 августа 2011

Да, есть более эффективный способ, но он потребует больше кода (таким образом, увеличивая затраты на обслуживание).

class base {
public:
    int x, y, z;
    // Default constructor
    base() {x = 0; y = 0; z = 0;};
    // Constructor to be called if you want to override the z value
    base(int zValue) { x=0; y=0; z=zValue; };
};

class derived : public base {
public:
    derived() : base(5) {};
};
1 голос
/ 15 августа 2011

Да, z назначается дважды в вашем примере, именно так, как это выглядит.

Чтобы сделать то, что вы хотите, вы можете сделать что-то вроде этого, что требует почти точно такое же количествокод (просто перемещая некоторые здесь и там):

class base {
public:
    int x, y, z;
    base(int z = 0) : x(), y(), z(z) { }
};

class derived : public base {
public:
    derived() : base(5) { } // with this one, z is assigned 5 once
    // or
    derived() { } // z is assigned 0 once
};
1 голос
/ 15 августа 2011

Конечно.Используйте то, что называется ctor-initializer:

class base {
public:
    int x, y, z;
    base(int z = 0) : x(0), y(0), z(z) {};
};

class derived : public base {
public:
    derived() : base(5) {}
};

Код после : и перед первым { в объявлении конструктора - ctor-initializer.(Некоторые люди называют это «списком инициализаторов», но ctor-initializer - это то, что стандарт C ++ называет его.)

Вы всегда должны использовать ctor-initializer s всякий раз, когда можете инициализировать членов класса к какому-либо значению.Хотя на самом деле это не имеет значения для int s, инициализация с использованием ctor-initializer s может быть быстрее, чем создание членов класса по умолчанию, а затем присваивание.

0 голосов
/ 15 августа 2011

Для уточнения ответа Эндрю, если вы действительно хотите убедиться, что все из base членов заданы только один раз, и самым эффективным способом вы можете использовать инициализатор списка, а не установка значений в конструкторе.

class base {
public:
    int x, y, z;
    base() : x(0), y(0), z(0) {};
    base( int xval, int yval, int zval ) : 
            x(xval), y(yval), z(zval) 
            { };
};

class derived : public base {
public:
    derived() : base( 0, 0, 5 ) {};
};

Большинство компиляторов генерируют тот же код для : x(_x), ..., что и просто установки значений в конструкторе, но я видел пару, которая этого не сделала.

0 голосов
/ 15 августа 2011

Определенно, вы можете сделать это.

Использовать member-initialization-list как:

class base {
public:
    int x, y, z;
    base(int a, int b, int c) : x(a), y(b), z(c) {}
                           //^^^^^^^^^^^^^^^^^^^ it's member-initialization-list!

};

class derived : public base {
public:
    derived() : base(0,0,5) {}
            // ^^^^^^^^^^^ call the specific base constructor
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...