Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > непонятка с конструкторами и указателями на ф-ии


Автор: Alek86 25.2.2008, 11:43
есть код
Код

typedef void (*Func)(const int&);

void func(const int& i) {
  PRINT_VALUE(i);
};

struct Functor {
  Functor(Func iop_func) : mp_func(iop_func) {}
  void operator()(const int& i) {
    mp_func(i);
  };
private:
  Func mp_func;
};

int main() {
  Functor f = Functor(func); // 1
  Functor(func);                   // 2
  system("pause");
}


строка // 1 нормально компилится
на строку //2 ругается: error C2512: 'Functor' : no appropriate default constructor available

понимаю, что прикол тут из легких, но не вижу. может, кто объяснит?

Автор: jorikdima 25.2.2008, 12:04
удалил

Автор: Fazil6 25.2.2008, 12:07
Цитата(Alek86 @  25.2.2008,  10:43 Найти цитируемый пост)
на строку //2 ругается: error C2512: 'Functor' : no appropriate default constructor available

а что ты пытаешься изобразить строкой
Код

 Functor(func);                   // 2

???

Автор: Alek86 25.2.2008, 12:11
Цитата(Fazil6 @  25.2.2008,  12:07 Найти цитируемый пост)
а что ты пытаешься изобразить строкой

создать временный объект типа Functorб передавая ему в качестве аргумента указатель на ф-ю

ЗЫ. Кстати, ведь неважно, что я хочу сделать, вопрос же не "а почему оно не так работает" smile


Цитата(jorikdima @  25.2.2008,  12:04 Найти цитируемый пост)
Добавте дефолтовый конструктор (без параметров) в структуру. Пусть он хоть ничего не делает, но объевлен быть должен.

должен? аргументируй smile

Автор: Fazil6 25.2.2008, 12:28
думаю, что дело в том, что компилятор не может такое выражение правильно разобрать (то, что ты имеешь в виду).
попробуй вот так
Код

Functor::Functor(func);                   // 2


Добавлено через 2 минуты и 25 секунд
Цитата(Alek86 @  25.2.2008,  11:11 Найти цитируемый пост)
создать временный объект типа Functorб передавая ему в качестве аргумента указатель на ф-ю

ведь вызов конструктора - это не создание объекта, а инициализация объекта

Автор: Alek86 25.2.2008, 12:37
Цитата(Fazil6 @  25.2.2008,  12:28 Найти цитируемый пост)
попробуй вот так

помогло, спасибо

Цитата(Fazil6 @  25.2.2008,  12:28 Найти цитируемый пост)
думаю, что дело в том, что компилятор не может такое выражение правильно разобрать

онлайн компилятор (других не имею) написал то же самое:
Цитата

C/C++ Front-end Compiler & Virtual Machine, Version 3.0.
Copyright © 1998-2003, Interstron, Ltd.

*** C++ FrontEnd
D:\soft\compiler\tmp\test.cpp.9 (18, 3): error 0417: Class 'class Functor' has no default constructor


то есть эта "фича" согласована со Стандартом?

Цитата(Fazil6 @  25.2.2008,  12:28 Найти цитируемый пост)
ведь вызов конструктора - это не создание объекта, а инициализация объекта

имхо, неверно
Код

struct S{};

int main() {
  S();
}

тут создается временный объект и сразу умирает

Автор: Daevaorn 25.2.2008, 12:38
Цитата(Fazil6 @  25.2.2008,  13:28 Найти цитируемый пост)

ведь вызов конструктора - это не создание объекта, а инициализация объекта 

хороший перлsmile и назван конструктор "конструктором" по ошибке, да?

Автор: Alek86 25.2.2008, 12:42
Цитата(Daevaorn @  25.2.2008,  12:38 Найти цитируемый пост)
хороший перл

не перл, если имелось в виду невыделение памяти

ведь new вызывает конструктор для уже выделенной памяти
просто в стеке вместо new память выделяет среда выполнения

Добавлено через 2 минуты и 51 секунду
кстати вопрос еще в силе, хоть и чуток изменен
это "Стандартное" поведение компилятора?

Автор: Daevaorn 25.2.2008, 12:45
Цитата(Alek86 @  25.2.2008,  13:42 Найти цитируемый пост)
не перл, если имелось в виду невыделение памяти

ведь new вызывает конструктор для уже выделенной памяти
просто в стеке вместо new память выделяет среда выполнения 

для тебя "создание объекта" и "выделенение памяти" одно и тоже?smile Второй перлsmile

Автор: Alek86 25.2.2008, 12:50
для меня "создание объекта" делится на "выделение памяти" и "инициализацию"
читай внимательней

или это третий перл?
тогда уж потрудись объяснить как На Самом Деле, когда из под стола вылезешь smile

Автор: Mayk 25.2.2008, 12:58
Цитата(Alek86 @  25.2.2008,  16:42 Найти цитируемый пост)

кстати вопрос еще в силе, хоть и чуток изменен
это "Стандартное" поведение компилятора? 

Судя по всему да.  Можно же делать int a( int (x) );
вот и тут похоже то же самое.

Тем более что если внести прототип ф-ции в main() то ошибка уже 
Цитата

"ComeauTest.c", line 15: error: "func" has already been declared in the current
          scope
    Functor(func);                   // 2

Автор: Alek86 25.2.2008, 13:01
Цитата(Mayk @  25.2.2008,  12:58 Найти цитируемый пост)
Можно же делать int a( int (x) );

а при чем тут int a( int (x) ) ?
наоборот, тут МОЖНО вызвать int(x) (создание временного объекта)


в моем же случае вызвать не получается

Добавлено через 1 минуту и 10 секунд
кстати
Код
int('s');

спокойно сьедает и не давится

Автор: Mayk 25.2.2008, 13:03
Код

typedef void (*Func)(const int&);
void func(const int& i) {
}

struct Functor {
  Functor(Func iop_func) : mp_func(iop_func) {}
  void operator()(const int& i) {
    mp_func(i);
  };
private:
  Func mp_func;
};

int main() {
  Functor f = Functor(func); // 1
  Functor((Func)func);                   // 2

}

вот так компилятор тоже понимает что  //2 ни разу не объявляет переменную под названием func

Добавлено @ 13:05
Цитата(Alek86 @  25.2.2008,  17:01 Найти цитируемый пост)



в моем же случае вызвать не получается

Какой вызов? О чем ты? Нет там никакого вызова акромя неявного вызова конструктора по умолчания. Там определятся переменная func с типом Functor. И компилятор не может найти дефолтовый конструктор. О чем и сообщает.

А у int(x) с конструированием по умолчанию проблем нет. В отличие от Functor'а.

Автор: Alek86 25.2.2008, 13:06
хм
если есть переменная  func типа Func, разве не должен компилятор (используя поиск-не-помню-кого) найти конструктор, который принимает переменную типа Func и заюзать его?

Автор: Fazil6 25.2.2008, 13:06
Цитата(Daevaorn @  25.2.2008,  11:38 Найти цитируемый пост)
хороший перл и назван конструктор "конструктором" по ошибке, да?


Цитата

12.1.2
A constructor is used to initialize objects of its class type. Because constructors do not have names, they
are never found during name lookup; however an explicit type conversion using the functional notation
(5.2.3) will cause a constructor to be called to initialize an object. [Note: for initialization of objects of
class type see 12.6. ]

вообще стандарт - сборник перлов. 
Создание объекта - выделение памяти + вызов конструктора.

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

#include <iostream>

typedef void (*Func)(const int&);

void func(const int& i) {
    
};

class A
{
public:
    A()
    {
        std::cout << "A::A()\n";
    }
};

struct Functor {
    Functor(Func iop_func) /*: mp_func(iop_func) */
    {
        std::cout << "Functor::Copy\n"; 
    }
    Functor()
    {std::cout << "Functor::Def\n"; };
    f()
    {
        std::cout << "Functor::f\n";
    }
    void operator()(const int& i) {
        mp_func(i);
    };
private:
    Func mp_func;
    A a;
};

int main() {
    
    Functor(func);  // 2
    func.f();
    

}


По сути вопроса смотрим стандарт пункт 6.8 Ambiguity resolution

Functor(func);  // 2  - это тоже самое что и  Functor func ;

Автор: Alek86 25.2.2008, 13:06
я про ситуацию
Код
 Functor(func);

Автор: Mayk 25.2.2008, 13:09
Цитата(Alek86 @  25.2.2008,  17:06 Найти цитируемый пост)

если есть переменная  func типа Func, разве не должен компилятор (используя поиск-не-помню-кого) найти конструктор, который принимает переменную типа Func и заюзать его? 

Если что-то выглядит как опредление это определение. Functor (func) выглядит как определение. Следовательно...

Автор: Alek86 25.2.2008, 13:13
ясно, спасибо, вопрос закрыт

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)