crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> Вопрос по с++, Помогите понять суть
igor_bogomolov
  опции профиля:
сообщение 13.7.2010, 23:34
Сообщение #1


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Вопрос из теста.
Раскрывающийся текст
#include <string>

class A
{
public :
      A(const std::string & s) : m_name(s) {}
      ~A() { }
private :
      std::string m_name;
};

int main(int c, char ** v)
{
      A r1(std::string(v[1]));

      const char * e = "Hello";
      A r2(std::string(e));
      std::string s(e);

      A r3(s);
      A r4(std::string("World"));
      return 0;../test/main.cpp:25: ошибка: запрос элемента ‘m_name’ в ‘r2’, имеющего не классовый тип ‘A(std::string)’ [quote][/quote]
}

Вопрос в тесте такой - сколько раз вызовется конструктор класса A при исполнении функции main. После ответа откомпилируй код для проверки, добавив какой-нибудь std::cout в конструктор A.

При первом просмотре (да и при втором, третьем, ...) я предположил, что конструктор вызовится 4 раза. Откомпилировав, получил всего два вызова. Пробовал воспользоваться отладчиком и впал в недоумение. r1 и r2 вообще не создаются, т.е. при компиляции эти строчки игнорируются. Сделал m_name публичным и попробовал обратиться к нему после создания r1. Получил ошибку компиляции
Цитата
ошибка: запрос элемента ‘m_name’ в ‘r1’, имеющего не классовый тип ‘A(std::string)’
При этом r3 и r4 создаются нормально и обращение к m_name не приводит к ошибке.

Помогите разобраться что происходит
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
DEADHUNT
  опции профиля:
сообщение 14.7.2010, 1:45
Сообщение #2


Активный участник
***

Группа: Участник
Сообщений: 430
Регистрация: 15.4.2009
Пользователь №: 686

Спасибо сказали: 26 раз(а)




Репутация:   2  


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


A r1(std::string(v[1])); может рассматриваться как функция A r1(std::string) с параметром по умолчанию v[1] и т. д.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 14.7.2010, 7:19
Сообщение #3


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(DEADHUNT @ 14.7.2010, 5:45) *
может рассматриваться как функция A r1(std::string)
в С++ нельзя функцию объявить внутри другой (например, в main). Поэтому здесь всё однозначно.
Если я правильно понял, то речь про такой код:
A r1(std::string(v[1]));
r1.m_name = "test";
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
DIMEDROLL
  опции профиля:
сообщение 14.7.2010, 7:29
Сообщение #4


Участник
**

Группа: Участник
Сообщений: 165
Регистрация: 28.9.2008
Из: Киев
Пользователь №: 304

Спасибо сказали: 23 раз(а)




Репутация:   0  


вижуал студия сразу выдает предупреждение:
Цитата
1>\testprocload.cpp(32) : warning C4930: 'A r1(std::string [])': prototyped function not called (was a variable definition intended?)
1>\testprocload.cpp(35) : warning C4930: 'A r2(std::string)': prototyped function not called (was a variable definition intended?)


Цитата
в С++ нельзя функцию объявить внутри другой (например, в main).

Что значит нельзя?
int main(int c, char ** v)
{
    int foo(int a);

    int r = foo(5);

    return 0;
}

int foo(int a){
    return a+=2;
}

отлично компилится

Сообщение отредактировал DIMEDROLL - 14.7.2010, 7:33
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 14.7.2010, 7:55
Сообщение #5


фрилансер
******

Группа: Участник
Сообщений: 2900
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


должен 4 раза вызваться - все 4 раза конструктор копирования (поскольку он явно определён)

строчки
A r1(std::string(v[1]));
и
A r3(s);
проигнорированы оптимизатором, так как эти локальные переменные нигде далее не использованы. Можно вывести их значение в поток тоже, чтобы они "остались", либо отрубить оптимизацию (а в дебаге должно само остаться, кстати)

Цитата(igor_bogomolov @ 14.7.2010, 2:34) *
Это связано с неоднозначностью, компилятор не может отличить декларацию прототипа функции от объявления переменной.

Ну ну :) С каких в C++ стало можно объявлять локальные функции ?

[offtop]
Цитата(igor_bogomolov @ 14.7.2010, 2:34) *
A r1(std::string(v[1])); может рассматриваться как функция A r1(std::string) с параметром по умолчанию v[1] и т. д.

а если бы это и было прототипом, то синтаксис неверен - какой ещё тут параметр по умолчанию ? :) std::string() - это конструктор класса std::string. А параметр по умолчанию пишется после "="
[/offtop]



Цитата(DIMEDROLL @ 14.7.2010, 10:29) *
Что значит нельзя?

ты объявил не функцию, сделал предопределение глобальной функции foo ИМХО
int foo(int a);
    
int main(int c, char ** v)
{
    int r = foo(5);
    
    return 0;
}


int foo(int a){
    return a+=2;
}


Хотя, студия, к примеру, не позволила бы сделать это внутри функции ))

Сообщение отредактировал Алексей1153 - 14.7.2010, 7:56
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 14.7.2010, 12:36
Сообщение #6


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Цитата(Алексей1153 @ 14.7.2010, 8:55) *
должен 4 раза вызваться - все 4 раза конструктор копирования (поскольку он явно определён)
Где вы увидели конструктор копирования? Он явно не определён.

Цитата(Алексей1153 @ 14.7.2010, 8:55) *
строчки
A r1(std::string(v[1]));
и
A r3(s);
проигнорированы оптимизатором, так как эти локальные переменные нигде далее не использованы
Вы не внимательно прочитали мое первое сообщение. r2 и r4 тоже нигде далее по коду не используются. Тем не менее они не с оптимизированны, как вы это объясните? С r3 вообще икаких проблем нет. Игнорируются r1 и r2.


Цитата(DEADHUNT)
Это связано с неоднозначностью, компилятор не может отличить декларацию прототипа функции от объявления переменной.
Цитата(DIMEDROLL)
1>\testprocload.cpp(32) : warning C4930: 'A r1(std::string [])': prototyped function not called (was a variable definition intended?)
1>\testprocload.cpp(35) : warning C4930: 'A r2(std::string)': prototyped function not called (was a variable definition intended?)

Спасибо, теперь понятно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
DEADHUNT
  опции профиля:
сообщение 14.7.2010, 13:09
Сообщение #7


Активный участник
***

Группа: Участник
Сообщений: 430
Регистрация: 15.4.2009
Пользователь №: 686

Спасибо сказали: 26 раз(а)




Репутация:   2  


Цитата(Litkevich Yuriy @ 14.7.2010, 8:19) *
в С++ нельзя функцию объявить внутри другой (например, в main). Поэтому здесь всё однозначно.

объявлять можно(declare), определять нельзя(define).

в стандарте также упоминается о неоднозначностях c с примерами - 6.8 Ambiguity resolution

8.3.6 Default arguments:
....
5. A default argument expression is implicitly converted (Clause 4) to the parameter type. The default argu-
ment expression has the same semantic constraints as the initializer expression in a declaration of a variable
of the parameter type, using the copy-initialization semantics (8.5). The names in the expression are bound,
and the semantic constraints are checked, at the point where the default argument expression appears.
Name lookup and checking of semantic constraints for default arguments in function templates and in mem-
ber functions of class templates are performed as described in 14.7.1. [ Example: in the following code, g
will be called with the value f(2):

с этим загнался.

Сообщение отредактировал DEADHUNT - 14.7.2010, 13:17
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 14.7.2010, 13:14
Сообщение #8


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Еще подсказали. Достаточно выражение в r1 и r2 заключить еще в одни скобки и неоднозначность пропадет.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 14.7.2010, 14:13
Сообщение #9


фрилансер
******

Группа: Участник
Сообщений: 2900
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


мдя, ночь без сна сказалась ))

Цитата(igor_bogomolov @ 14.7.2010, 15:36) *
Где вы увидели конструктор копирования? Он явно не определён.

Да, это я протупил. Там тип ссылки же не A

Цитата(igor_bogomolov @ 14.7.2010, 15:36) *
r2 и r4 тоже нигде далее по коду не используются.

Да, теперь вижу

Сорри за дезинформацию :)

Сообщение отредактировал Алексей1153 - 14.7.2010, 14:13
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ЙаМайскЫйПчОЛ
  опции профиля:
сообщение 14.7.2010, 17:17
Сообщение #10


Участник
**

Группа: Участник
Сообщений: 154
Регистрация: 10.7.2008
Из: СПб
Пользователь №: 232

Спасибо сказали: 7 раз(а)




Репутация:   5  


Этож... 3.14дец
Так всетаки он это чуствовал как прототип функции???
А то у нас тут работа остановилась.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 23.9.2020, 2:55