в статическом классе (с конструкцией delete) private Object не является вызовом или использует собственный метод-член [duplicate]

Если вы хотите сохранить постоянное хранилище, между различными страницами , вы должны использовать сеансы, поставив session_start(); в начало вашего скрипта. После этого каждая переменная $ _SESSION [$ x] будет сохранена и будет доступна для ваших скриптов.

Однако в этом конкретном случае, отвечая на ваш вопрос: «Есть ли способ сохранить значения из массива, чтобы форма всегда была заполнена последними сохраненными значениями? », проще просто использовать переменную $ _POST, если она уже существует:

$v)  filter_input(INPUT_POST,$k,FILTER_SANITIZE_SPECIAL_CHARS);

//save the arrays with the form data
$images = array($_POST["i0"], $_POST["i1"], $_POST["i2"], $_POST["i3"]);
$urls   = array($_POST["u0"], $_POST["u1"], $_POST["u2"], $_POST["u3"]);
$titles = array($_POST["t0"], $_POST["t1"], $_POST["t2"], $_POST["t3"]);


//print the arrays
print_r($images);
print_r($urls);
print_r($titles);
//create the form and populate it
echo "

"; $x++; } ?>

Примечание: эта строка foreach($_POST as $k=>$v) filter_input(INPUT_POST,$k,FILTER_SANITIZE_SPECIAL_CHARS); должно быть достаточно, чтобы защитить вас от основных атак XSS. Обратите также внимание на то, что в целом лучше следовать шаблону перезагрузки страниц с помощью GET после POST , что делает вас менее восприимчивыми к формированию повторных представлений, и в этом случае использование сессий для хранения является лучшим решением.

181
задан codeling 18 December 2015 в 12:56
поделиться

7 ответов

Вы должны фактически определить статический член где-нибудь (после определения класса). Попробуйте следующее:

class Foo { /* ... */ };

const int Foo::MEMBER;

int main() { /* ... */ }

Это должно избавиться от неопределенной ссылки.

183
ответ дан Drew Hall 15 August 2018 в 17:57
поделиться
  • 1
    Хорошая точка, встроенная статическая константная инициализация const, создает скользящую константу целого, которую вы не можете взять по адресу, а вектор принимает ссылочный параметр. – Evan Teran 7 November 2008 в 19:08
  • 2
    Этот ответ касается только первой части вопроса. Вторая часть намного интереснее: почему добавление ника NOP делает работу без необходимости внешней декларации? – nobar 1 February 2011 в 01:48
  • 3
    Я просто потратил немало времени на выяснение того, что если определение класса находится в файле заголовка, то распределение статической переменной должно быть в файле реализации, а не в заголовке. – shanet 14 July 2012 в 04:06
  • 4
    @shanet: Очень хороший момент - я должен был упомянуть об этом в своем ответе! – Drew Hall 14 July 2012 в 04:10
  • 5
    Но если я объявляю его как const, разве мне не возможно изменить значение этой переменной? – Namratha 27 November 2012 в 06:57

Aaa.h

class Aaa {

protected:

    static Aaa *defaultAaa;

};

Aaa.cpp

// You must define an actual variable in your program for the static members of the classes

static Aaa *Aaa::defaultAaa;
9
ответ дан ollo 15 August 2018 в 17:57
поделиться

Не знаю, почему работает бросок, но Foo :: MEMBER не выделяется до тех пор, пока Foo не будет загружен, и поскольку вы никогда не загружаете его, он никогда не выделяется. Если у вас есть ссылка на Foo где-то, это, вероятно, сработает.

1
ответ дан Paul Tomblin 15 August 2018 в 17:57
поделиться
  • 1
    Я думаю, что вы отвечаете на свой вопрос: бросок работает, потому что он создает (временную) ссылку. – Jaap Versteegh 30 November 2011 в 17:43

Проблема возникает из-за интересного столкновения новых функций C ++ и того, что вы пытаетесь сделать. Во-первых, давайте посмотрим на подпись push_back:

void push_back(const T&)

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

#include <vector>

class Foo {
public:
    static const int MEMBER;
};

const int Foo::MEMBER = 1; 

int main(){
    std::vector<int> v;
    v.push_back( Foo::MEMBER );       // undefined reference to `Foo::MEMBER'
    v.push_back( (int) Foo::MEMBER ); // OK  
    return 0;
}

Это потому, что есть фактический объект где-то, у которого есть это значение, хранящееся в нем. Если, однако, вы переключитесь на новый метод указания статических константных элементов, как вы уже выше, Foo::MEMBER больше не является объектом. Это константа, несколько схожа с:

#define MEMBER 1

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

70
ответ дан phoenix 15 August 2018 в 17:57
поделиться
  • 1
    Это имеет смысл – Evan Teran 7 November 2008 в 19:06
  • 2
    спасибо, что помогли ..., которые могли бы претендовать на stackoverflow.com/questions/1995113/strangest-language-feature , если его еще нет ... – Andre Holzner 3 December 2010 в 14:45
  • 3
    Также стоит отметить, что MSVC принимает безличную версию без жалоб. – porges 27 June 2012 в 00:49
  • 4
    -1: Это просто неверно. Вы все еще должны определять статические члены, инициализированные inline, когда они odr-used где-то. То, что оптимизация компилятора может избавиться от ошибки компоновщика, не меняет этого. В этом случае преобразование lvalue-to-rvalue (благодаря слиянию (int)) происходит в блоке трансляции с идеальной видимостью константы, а Foo::MEMBER больше не odr-used . Это контрастирует с первым вызовом функции, где ссылка передается и оценивается в другом месте. – Lightness Races in Orbit 6 October 2014 в 23:12

Что касается второго вопроса: push_ref принимает ссылку как параметр, и вы не можете иметь ссылку на static const memeber класса / struct. После вызова static_cast создается временная переменная. И ссылка на этот объект может быть передана, все работает отлично.

Или, по крайней мере, мой коллега, который разрешил это, сказал.

0
ответ дан Quarra 15 August 2018 в 17:57
поделиться

Стандарт C ++ требует определения для вашего статического члена константы, если определение каким-то образом необходимо.

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

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

Это действительно интересный случай, и я на самом деле думаю, что стоит подняться вопрос, чтобы std был изменен на имеют одинаковое поведение для вашего постоянного члена!

Хотя, в каком-то странном виде это можно рассматривать как законное использование унарного оператора «+». В основном результат unary + является rvalue, поэтому применяются правила привязки rvalues ​​к ссылкам const, и мы не используем адрес нашего статического члена const:

v.push_back( +Foo::MEMBER );
57
ответ дан Richard Corden 15 August 2018 в 17:57
поделиться
  • 1
    +1. Да, конечно, странно, что для объекта x типа T выражение "(T) x" могут быть использованы для связывания константы ref, тогда как простой "x" не может. Мне нравится ваше наблюдение за «унарным +». Кто бы мог подумать, что бедный маленький «унарный +» на самом деле было полезно ... :) – j_random_hacker 29 May 2009 в 11:38
  • 2
    Думая об общем случае ... Есть ли какой-либо другой тип объекта в C ++, который обладает свойством, что он (1) может использоваться как lvalue только в том случае, если он определен, но (2) может быть преобразован в rvalue без определены? – j_random_hacker 29 May 2009 в 11:51
  • 3
    Хороший вопрос, и по крайней мере на данный момент я не могу придумать никаких других примеров. Вероятно, это возможно только потому, что комитет в основном просто повторно использовал существующий синтаксис. – Richard Corden 29 May 2009 в 13:47
  • 4
    @RichardCorden: как унарный + разрешил это? – Blood-HaZaRd 28 June 2018 в 15:10
  • 5
    @ Blood-HaZaRd: перед ссылками rvalue единственной перегрузкой push_back была const &. Использование члена напрямую приводило к тому, что член привязывался к ссылке, что требовало наличия адреса. Однако добавление + создает временное значение со значением члена. Ссылка затем привязывается к этому временному, а не требует, чтобы у члена был адрес. – Richard Corden 13 July 2018 в 10:48

С C ++ 11 приведенное выше возможно для базовых типов как

class Foo {
public:  
  static constexpr int MEMBER = 1;  
};

Часть constexpr создает статическое выражение в противоположность статическому variable - и это ведет себя так же, как чрезвычайно простое определение встроенного метода. Тем не менее подход оказался немного шатким с C-string constexprs внутри классов шаблонов.

0
ответ дан starturtle 15 August 2018 в 17:57
поделиться