Инициализация констант C ++ и наследование - PullRequest
3 голосов
/ 17 июня 2010

Я хочу инициализировать константу в дочернем классе, а не в базовом классе. И используйте его, чтобы избавиться от динамического выделения памяти (я уже знаю размеры массивов, и будет несколько дочерних классов с разными константами).
Поэтому я стараюсь:

class A {
public:
    const int x;

    A() : x(0) {}
    A(int x) : x(x) {}
    void f() {
        double y[this->x];
    }
};

class B : A {
    B() : A(2) {}
};

Довольно просто, но компилятор говорит:

ошибка C2057: ожидаемое постоянное выражение

Как я могу сказать компилятору, что это действительно константа?

Ответы [ 4 ]

4 голосов
/ 17 июня 2010

Это не константа, хотя. Это все еще может быть изменено конструктором. Для размера массива допустима только константа времени компиляции . Когда компилятор говорит «константное выражение», это означает не выражение, которое возвращает постоянное значение, а константу, например «52» или «45» или что-то в этом духе.

Вместо этого используйте std::vector.

РЕДАКТИРОВАТЬ: В ответ на "Я знаю размеры массива, и будет несколько дочерних классов с различными константами"

Единственный способ сделать это - использовать шаблон.

template<size_t x>
class A {
public:
    void f() {
        double y[x];
    }
};

typedef A<2> B;
2 голосов
/ 17 июня 2010

Ожидаемого поведения можно добиться с помощью следующего шаблона.

Обратите внимание, что это на самом деле ненадежно, отвратительно и может использоваться только как "образец".Вместо этого используйте std::vector.

template <size_t a = 0>
class A {
public:
   A() { }

   void f() {
      int y[a];
      y[0] = 5;
   }
};

class B : A<2> {
   B() { }
};

void main() {
   A<1> a;
   a.f();

   // Undefined behaviour - creating an array of size 0
   // At least, MSVS2008 treats it as an error :)
   // A<0> a_;
}
1 голос
/ 17 июня 2010

Я не знаю, будет ли это работать для ваших целей, но одной из возможностей было бы сделать его параметром шаблона:

template <int size>
class A { 
    double y[size];
};

В этом случае вы, вероятно, захотите создать экземплярA в B вместо использования наследования.

Другая очевидная возможность - вместо этого использовать объект tr1::array.Это также шаблон, поэтому идея почти такая же, но она уже написана, протестирована и работает, так что вы можете избежать всего этого.Если ваш компилятор не предоставляет классы TR1, Boost имеет в основном соответствующую реализацию (boost::array).

1 голос
/ 17 июня 2010

Есть «константа», а затем «константа». Если вы хотите разместить массив в стеке подобным образом, то компилятору нужна длина массива во время компиляции, и на основании того, что вы там указали, он не может этого понять. Интересно, что gcc поддерживает расширение (не поддерживается в стандарте C ++), которое позволяет выделять стеки для переменных длин.

...