Нельзя ли использовать только точку (.) Для доступа к членам пространства имен и статическим членам класса [duplicate]

Я думаю, что это должно сделать трюк. Я просто добавил if(isset и добавил конкатенацию к переменным в теле, чтобы отделить PHP от HTML.

<?php
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
    $from = 'From: yoursite.com'; 
    $to = 'contact@yoursite.com'; 
    $subject = 'Customer Inquiry';
    $body = "From:" .$name."\r\n E-Mail:" .$email."\r\n Message:\r\n" .$message;

if (isset($_POST['submit'])) 
{
    if (mail ($to, $subject, $body, $from)) 
    { 
        echo '<p>Your message has been sent!</p>';
    } 
    else 
    { 
        echo '<p>Something went wrong, go back and try again!</p>'; 
    }
}

?>
32
задан manlio 9 April 2016 в 20:00
поделиться

7 ответов

Почему C ++ не использует ., где он использует ::, потому что именно так определяется язык. Одна из правдоподобных причин - ссылаться на глобальное пространство имен, используя синтаксис ::a, как показано ниже:

int a = 10;
namespace M
{
    int a = 20;
    namespace N
    {
           int a = 30;
           void f()
           {
              int x = a; //a refers to the name inside N, same as M::N::a
              int y = M::a; //M::a refers to the name inside M
              int z = ::a; //::a refers to the name in the global namespace

              std::cout<< x <<","<< y <<","<< z <<std::endl; //30,20,10
           }
    }
}

Онлайн-демонстрация

Не знаю, как Java решает это. Я даже не знаю, есть ли в Java глобальное пространство имен. В C # вы ссылаетесь на глобальное имя, используя синтаксис global::a, что означает, что даже C # имеет оператор ::.


, но я не могу представить ни одной ситуации, в которой синтаксис

Кто сказал, что синтаксис, подобный a.b::c, не является законным?

Рассмотрим эти классы:

struct A
{
    void f() { std::cout << "A::f()" << std::endl; }
};

struct B : A
{
    void f(int) { std::cout << "B::f(int)" << std::endl; }
};

Теперь см. Это ( ideone ):

B b;
b.f(10); //ok
b.f();   //error - as the function is hidden

b.f() не может быть вызвано так, как функция скрыта, а GCC дает это сообщение об ошибке:

error: no matching function for call to ‘B::f()’

Для вызова b.f() (или, скорее, A::f()) вам нужен оператор разрешения области видимости:

b.A::f(); //ok - explicitly selecting the hidden function using scope resolution

Демо на идеоне

20
ответ дан Nawaz 22 August 2018 в 07:10
поделиться
  • 1
    Это не объясняет, почему вы не можете просто сказать b.A.f вместо b.A::f. Если A является typename вместо переменной или функции, то использование . может легко означать scope resolution вместо обычного значения. – Nicol Bolas 18 February 2012 в 05:42
  • 2
    @NicolBolas: Обновленный ответ. – Nawaz 18 February 2012 в 05:49
  • 3
    – Nicol Bolas 18 February 2012 в 06:08
  • 4
    Предположение, которое я сделал относительно a.b::c неразумным, вызывает у меня путаницу. Принял этот ответ, потому что я думаю, что он так же хорош, как и другие, но также указывает на мою ошибку. – Karu 18 February 2012 в 06:57
  • 5
    В Java нет глобального пространства имен, потому что все внутри одного класса. – Karl Knechtel 18 February 2012 в 07:08

Почему у C ++ есть оператор :: вместо использования. оператор для этой цели?

Причина дана самим Страуступом:

В C с классами точка использовалась для выражения членства в классе как а также выражение выбора элемента определенного объекта.

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

(Bjarne Stroustrup A История C ++: 1979-1991 стр. 21 - § 3.3.1)

Кроме того, это правда, что

они делают разные вещи, поэтому они могут выглядеть иначе

< / blockquote>

действительно

В N::m ни N, ни m не являются выражениями со значениями; N и m - имена, известные компилятору, а :: выполняет разрешение области (времени компиляции), а не оценку выражения. Можно представить себе возможность перегрузки x :: y, где x - это объект, а не пространство имен или класс, но это, вопреки первым появлениям, включает введение нового синтаксиса (чтобы разрешить expr::expr). Неясно, какие преимущества принесет такое усложнение.

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

(Bjarne Stroustrup's C ++ Стиль и техника FAQ )

4
ответ дан manlio 22 August 2018 в 07:10
поделиться

В отличие от Java, C ++ имеет множественное наследование. Вот один из примеров, где важное значение имеет разрешение области видимости, о которой вы говорите:

#include <iostream>
using namespace std;
struct a
{
    int x;
};
struct b
{
    int x;
};
struct c : public a, public b
{
    ::a a;
    ::b b;
};
int main() {
    c v;
    v.a::x = 5;
    v.a.x = 55;
    v.b::x = 6;
    v.b.x = 66;
    cout << v.a::x << " " << v.b::x << endl;
    cout << v.a.x << " " << v.b.x << endl;
    return 0;
}
26
ответ дан Nicol Bolas 22 August 2018 в 07:10
поделиться
  • 1
    Технически это не о множественном наследовании. Речь идет о том, чтобы назвать ваши переменные теми же именами, что и ваши производные классы. – Nicol Bolas 18 February 2012 в 06:07
  • 2
    Почему вы не можете написать test.foo.blah = 10? Или test.base.blah = 10, где base - ключевое слово? – Nawaz 18 February 2012 в 06:13
  • 3
    @Nawaz: Потому что введение ключевого слова lot сложнее, чем введение оператора. И test.foo.blah неоднозначен; это элемент blah или thingy члена базового класса blah? Java (как я понимаю) оборачивается этим, заявляя, что это всегда член; вы можете получить только переменные-члены базового класса, нажав тип. – Nicol Bolas 18 February 2012 в 06:15
  • 4
    @Nawaz: Потому что это не даст никакого указания на , который base вы хотели использовать. – Mankarse 18 February 2012 в 06:16
  • 5
    @NicolBolas: Это может быть труднее с точки зрения автора компилятора, но с точки зрения программистов base.blah намного проще (и менее неудобно). – Nawaz 18 February 2012 в 06:21
  • 6
    @Nawaz: Если, конечно, ваш код никогда не использовал идентификатор base в любом месте. Это вполне возможно. Ключевые слова не сложно из-за компилятора; это сложно, потому что это делает вещи, которые использовали , эти ключевые слова ломаются. Даже ключевое слово, зависящее от контекста, означает, что вы не можете иметь тип с именем base. – Nicol Bolas 18 February 2012 в 06:31
  • 7
    У C ++ не было множественного наследования при вводе оператора ::. См. Руководство Cfront E, стр. 22 (25 в pdf) - ::, но никаких признаков множественного наследования в описании классов нет. – Jules 3 April 2016 в 16:20

Чтобы ответить на окончательный бит вопроса о приоритете оператора:

class A {
public:
  char A;
};

class B : public A {
public:
  double A;
};

int main(int c, char** v)
{
  B myB;
  myB.A = 7.89;
  myB.A::A = 'a';
  // On the line above a hypothetical myB.A.A
  // syntax would parse as (myB.A).A and since
  // (myB.A) is of type double you get (double).A in the
  // next step. Of course the '.' operator has no
  // meaning for doubles so it causes a syntax error. 
  // For this reason a different operator that binds
  // more strongly than '.' is needed.
  return 0;
}
3
ответ дан nolandda 22 August 2018 в 07:10
поделиться
  • 1
    Вы говорите, что синтаксический анализатор не мог просто подождать и проверить следующий токен, чтобы убедиться, что это ., прежде чем принимать решение о двусмысленности? – Nicol Bolas 18 February 2012 в 06:23
  • 2
    Нет, конечно, такой парсер можно было бы написать. Промежуточный результат будет неоднозначным, и когда появится следующий токен, вы можете предположить, что пользователь не имел в виду сделать синтаксическую ошибку. Поэтому в этом смысле это не является строго необходимым, но оператор «::» полезен в другом месте, и авторы синтаксического анализатора C ++ уже имеют проблемы. :) – nolandda 19 February 2012 в 09:02
  • 3
    @nolandda Первая версия C ++, & quot; Cpre & quot; имел рабочий синтаксический анализатор, который использовал . для разрешения области (см. исходный код Cfront, который был написан для компиляции Cpre: softwarepreservation.org/projects/c_plus_plus/cfront/release_e/… ) , Выяснив, как это сделать, я сомневаюсь, что Страуструп тогда отказался бы от этого, когда он переопределит язык. Поэтому я не думаю, что техническая сложность его использования была частью причины. – Jules 3 April 2016 в 16:23

Я всегда предполагал, что C ++ dot / :: использование было выбором стиля, чтобы сделать код более удобным для чтения. Как пишет OP, «они делают разные вещи, поэтому они должны выглядеть по-другому».

Начиная с C ++, давным-давно, до C #, я нашел использование пустых строк. Я привык видеть A::doStuff(); B.doStuff();, и знать, что первая является регулярной функцией, в пространстве имен, а вторая является функцией-членом в экземпляре B.

C ++ - это, может быть, мой пятый язык, после Basic, Assembly, Pascal и Fortran, поэтому я не думаю, что это синдром первого языка, и теперь я больше программист на C #. Но, ИМХО, если вы использовали оба варианта, двойная двоеточие типа C ++ для пространств имен лучше читается. Я чувствую, что Java / C # выбрали точки для того, чтобы (успешно) облегчить фронт кривой обучения.

1
ответ дан Owen Reynolds 22 August 2018 в 07:10
поделиться

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

1
ответ дан Vishal Parekh 22 August 2018 в 07:10
поделиться
26
ответ дан Nicol Bolas 5 November 2018 в 04:55
поделиться
Другие вопросы по тегам:

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