Когда я могу использовать предварительную декларацию?

Создайте список элементов на основе их weights:

items = [1, 2, 3, 4, 5, 6]
probabilities= [0.1, 0.05, 0.05, 0.2, 0.4, 0.2]
# if the list of probs is normalized (sum(probs) == 1), omit this part
prob = sum(probabilities) # find sum of probs, to normalize them
c = (1.0)/prob # a multiplier to make a list of normalized probs
probabilities = map(lambda x: c*x, probabilities)
print probabilities

ml = max(probabilities, key=lambda x: len(str(x)) - str(x).find('.'))
ml = len(str(ml)) - str(ml).find('.') -1
amounts = [ int(x*(10**ml)) for x in probabilities]
itemsList = list()
for i in range(0, len(items)): # iterate through original items
  itemsList += items[i:i+1]*amounts[i]

# choose from itemsList randomly
print itemsList

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

Кроме того, это может быть интересным.

577
задан Bugs 22 March 2017 в 12:10
поделиться

9 ответов

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

Принятие следующего предописания.

class X;

Вот то, что Вы можете и не можете сделать.

, Что можно сделать с неполным типом:

  • Объявляют, что участник указатель или ссылка на неполный тип:

    class Foo {
        X *p;
        X &r;
    };
    
  • Объявляют функции или методы, которые принимают/возвращают неполные типы:

    void f1(X);
    X    f2();
    
  • Определяют функции или методы, которые принимают/возвращают указатели/ссылки на неполный тип (но не используя его участников):

    void f3(X*, X&) {}
    X&   f4()       {}
    X*   f5()       {}
    

, Что Вы не можете сделать с неполным типом:

  • Использование это как Использование базового класса

    class Foo : X {} // compiler error!
    
  • это для объявления участника:

    class Foo {
        X m; // compiler error!
    };
    
  • Определяют функции или методы с помощью этого Использования типа

    void f1(X x) {} // compiler error!
    X    f2()    {} // compiler error!
    
  • его методы или поля, на самом деле пытаясь разыменовать переменную с неполным типом

    class Foo {
        X *m;            
        void method()            
        {
            m->someMethod();      // compiler error!
            int i = m->someField; // compiler error!
        }
    };
    
<час>

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

, Например, std::vector<T> требует, чтобы его параметр был полным типом, в то время как boost::container::vector<T> не делает. Иногда, полный тип требуется, только если Вы используете определенные функции членства; дело обстоит так для [1 110] , например.

А хорошо зарегистрированный шаблон должен указать в его документации на все требования своих параметров, включая то, должны ли они быть полными типами или нет.

925
ответ дан Luc Touraille 22 March 2017 в 22:10
поделиться

Основное правило состоит в том, что можно только передать - объявляют классы, расположение памяти которых (и таким образом функции членства и элементы данных) не должны быть известны в файле, который Вы передаете - объявляют это.

Это исключило бы базовые классы и что-либо кроме классов, используемых через ссылки и указатели.

43
ответ дан Timo Geusch 22 March 2017 в 22:10
поделиться
  • 1
    IIF не определяется здесь, таким образом, эта реализация больше, чем это похоже. – hubalu 6 December 2013 в 10:16

В файле, в котором Вы используете только Указатель или Ссылку на класс. И никакой участник/функция членства не должен быть вызван мысль они Указатель / ссылка.

с class Foo;//предописание

Мы можем объявить элементы данных типа Foo* или Foo&.

Мы можем объявить (но не определить), функции с аргументами и/или возвращаемые значения, типа Foo.

Мы можем объявить статические элементы данных типа Foo. Это вызвано тем, что статические элементы данных определяются вне определения класса.

5
ответ дан yesraaj 22 March 2017 в 22:10
поделиться

А также указатели и ссылки на неполные типы, можно также объявить прототипов функции, которые указывают параметры и/или возвращаемые значения, которые являются неполными типами. Однако Вы не можете определять функция, имеющая параметр или тип возврата, который является неполным, если это не указатель или ссылка.

Примеры:

struct X;              // Forward declaration of X

void f1(X* px) {}      // Legal: can always use a pointer
void f2(X&  x) {}      // Legal: can always use a reference
X f3(int);             // Legal: return value in function prototype
void f4(X);            // Legal: parameter in function prototype
void f5(X) {}          // ILLEGAL: *definitions* require complete types
28
ответ дан jxramos 22 March 2017 в 22:10
поделиться
  • 1
    Вы использовали ПРАГМУ тем же путем, я сделал? – Nick Perkins 12 April 2010 в 23:10

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

3
ответ дан Naveen 22 March 2017 в 22:10
поделиться

Вы будете обычно хотеть использовать предописание в заголовочном файле классов, когда Вы захотите использовать другой тип (класс) в качестве члена класса. Вы не можете использовать вперед - объявленный классами методы в заголовочном файле, потому что C++ еще не знает определение того класса в той точке. Это - логика, которую необходимо переместить в .cpp-файлы, но если Вы используете шаблонные функции, необходимо уменьшить их только до части, которая использует шаблон, и переместите ту функцию в заголовок.

0
ответ дан Patrick Glandien 22 March 2017 в 22:10
поделиться

Возьмите его, что предописание доберется, Ваш код для компиляции (obj создается). Соединение однако (exe создание) не будет успешно, если определения не будут найдены.

0
ответ дан Sesh 22 March 2017 в 22:10
поделиться
  • 1
    Более простой и хороший ответ! Это работает отлично для меня – Marco Herrarte 10 April 2014 в 20:54

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

3
ответ дан dirkgently 22 March 2017 в 22:10
поделиться

Лакос различает использование класса

  1. только по имени (для которого достаточно прямого объявления) и
  2. in-size (для что необходимо определение класса).

Я никогда не видел, чтобы это произносилось более кратко :)

32
ответ дан 22 November 2019 в 22:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: