2017-01-27 23 views
0

Вот мой кодехЬегп Const по умолчанию построенный объект

#include <iostream> 
using namespace std; 

class Q 
{ 
public: 
    Q() { cout << "constructor" << endl; } 
}; 

extern const Q t/*()*/; //A 
const Q s/*()*/; //B 

int main() 
{ 
    const Q t/*()*/; 
} 

Я ожидаю, что линия с пометкой «А» означает, что я создаю объект т типа Q, чья связь является внешним, и чьи поля не может быть изменен. Создание выполняется конструктором без аргументов, которые я предоставил.

В основном я ожидаю, что локальный объект t типа Q создается таким же образом, хотя его привязка обязательно будет именно этим файлом, и на самом деле его объем и продолжительность будут только для основного.

C++ позволяет мне помещать или не помещать скобки в const Q t/() /; в основном. В глобальной области видимости в строке A я могу поставить или не поставить круглые скобки, и конструктор не будет вызываться ни в одном из способов.

В строке B мне разрешено не помещать скобки, так как в противном случае компилятор будет смущен, если я определяю прототип функции.

Мои вопросы:

  1. Почему я позволил гибкость ставить() или не соответствует // А, учитывая, что в линии // В этой гибкости не существует?

  2. Независимо от моего выбора в 1., я обнаружил, что «конструктор» не печатается линией A, хотя он напечатан в строке B. Почему? На самом деле у меня нет ожиданий. С одной стороны, было бы разумно напечатать его, так как мы видим в основном, что C++ понимает вызов конструктора с 0 аргументами даже без круглых скобок. С другой стороны, если бы это было так, то как я мог бы сделать объявление, не определяющее тип класса?

+0

Ir не совсем очевидно, что вы просите, но этот 'const Q s()' ничего не создает, он объявляет функцию. Поиск здесь и в другом месте для «наиболее неприятного разбора». –

+0

@NeilButterworth Как я могу уточнить, что я прошу? Паренс прокомментирован. Они не будут допущены, как вы и я оба отметили. – Jeff

+0

Им не разрешат. Когда вы публикуете здесь _don't_ пост, прокомментированный код - это просто затрудняет понимание того, о чем вы на самом деле спрашиваете, и требует от нас редактирования кода, если мы хотим его скомпилировать. –

ответ

0

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

Это относится ко всем вашим заявкам, а не только к B, как вы, кажется, верите. Почему вы утверждаете, что «эта гибкость не существует» для строки B мне нечетко: вы можете включить () в строку B или опустить ее. В любом случае объявление будет совершенно корректным, за исключением того, что с () он объявит функцию. (То есть это не просто «гибкость», а скорее очень резкое качественное изменение.)

Для линии В проблема действительно не существует, так как строка В не использует ключевое слово extern. Без extern строка B представляет собой объект определение независимо от того, используете ли вы явный инициализатор или нет. И в вашем случае оставить его как есть (без ()) по-прежнему вызывает конструкцию по умолчанию, как и вы. То же самое относится к локальной декларации внутри main.

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

Для того, чтобы обойти эту проблему в «классическом» C++ 98 вы вынуждены использовать

extern const Q t = Q(); 

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

В современном C++ (C++ 11 и позже), вы можете сделать это в определении (с возведением по умолчанию) с помощью {} инициализатору

extern const Q t{}; 

или

extern const Q t = {}; 

{} основанное синтаксис по очевидным причинам не вызывает каких-либо двусмысленностей с объявлениями функций.