Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
atomohod
20 / 20 / 1
Регистрация: 01.04.2010
Сообщений: 57
#1

CALLBACK. Нужна помощь - C++

06.11.2011, 21:52. Просмотров 1207. Ответов 28
Метки нет (Все метки)

Всем привет!

Есть такой код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ExpressionCalculator
{
private:
    double(ExpressionCalculator::*fn)(double,double,double,double);
public:
    ExpressionCalculator(void);
    ~ExpressionCalculator(void);
 
    double f1(double a, double b, double c, double d);
    double f2(double a, double b, double c, double d);
    double f3(double a, double b, double c, double d);
 
    double Calculate(double a, double b, double c, double d);
 
};
в *.cpp пробую:
C++
1
2
3
4
5
double ExpressionCalculator::Calculate(double a, double b, double c, double d)
{
    double tmp = fn(a,b,c,d);
    return tmp;
}
на
C++
1
double tmp = fn(a,b,c,d);
получаю при компиляции

error C2064: результатом вычисления фрагмента не является функция, принимающая 4 аргументов

подскажите, что не так?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.11.2011, 21:52
Здравствуйте! Я подобрал для вас темы с ответами на вопрос CALLBACK. Нужна помощь (C++):

For_each и аргументы callback-функции; Как передать callback'у больше одного аргумента - C++
Изучаю контейнеры и алгоритмы stl по Майерсу . С непривычки слегка охренел и запутался в них . В общем есть у меня простой вызов...

Нужна помощь начинающему (while). - C++
Собствено вот код: //While DEMO //прога выводит количество выполненых цыклов while #include <stdio.h> #include <lostream.h> int...

Нужна помощь с комментариями. - C++
Нужны комментарии и сделать так, чтобы вводилось только пятизначное число. #include "stdafx.h" #include <stdlib.h> #include...

Нужна помощь с MD5 на Си/Си++ - C++
Мне нужны либо библиотеки, в которых реализована функция-аналог md5() на PHP, либо код. Но библиотеки для висуалс++ не предлагать. Также...

Нужна помощь в исправлении - C++
эта программа расчитывает значения отрезка интегрирования (x1, x2) один для всех трех интегралов, помогите сделать так, чтобы нужно было...

Нужна помощь с циклами - C++
Помогите, пожалуйста, нету никаких идей. Пользователь вводит число. Показать сколько в данном числе чисел и сумму этих чисел. Нужно...

28
-=ЮрА=-
Заблокирован
Автор FAQ
06.11.2011, 22:13 #2
Цитата Сообщение от atomohod Посмотреть сообщение
fn(a,b,c,d);
- очень просто в прототип fn содержит отличное от 4-х число аргументов...

Добавлено через 1 минуту

Не по теме:

Вы наверное что то типа такого хотели сделать

C++
1
2
for(n = 1; n < 3; n++)
   tmp = fn(a,b,c,d);
- просто другой ошибки в голову не пришло

0
atomohod
20 / 20 / 1
Регистрация: 01.04.2010
Сообщений: 57
06.11.2011, 22:20  [ТС] #3
эмм, я наверно чего-то не понимаю..
я же в *.h файле описал

C++
1
double(ExpressionCalculator::*fn)(double,double,double,double);
Я же правильно понимаю что это значит что fn принимает 4ре параметра типа double и возращает double.

Просто где то в других методах я говорю что:

C++
1
fn = &ExpressionCalculator::f3;
например
0
Bers
Заблокирован
06.11.2011, 22:45 #4
приведите весь код
0
-=ЮрА=-
Заблокирован
Автор FAQ
06.11.2011, 23:09 #5
atomohod, как вариант
C++
1
double tmp = &fn(a,b,c,d);
Цитата Сообщение от Bers Посмотреть сообщение
приведите весь код
- без этого непонятно что к чему
0
atomohod
20 / 20 / 1
Регистрация: 01.04.2010
Сообщений: 57
07.11.2011, 00:03  [ТС] #6
спасибо, вот код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#pragma once
#include <math.h>
#include <iostream>
 
enum Errors 
{ 
    DivBy0, 
    Negative,
    InvalidLgArgument
};
 
class CalculatingError
{
private:
    void Negative();
    void DivBy0();
    void InvalidLgArgument();
 
    Errors _error;
 
public: 
 
    CalculatingError(Errors error);
    ~CalculatingError();
 
    void RaiseError();
 
};
 
class ExpressionCalculator
{
private:
    double(ExpressionCalculator::*f)(double,double,double,double);
public:
    ExpressionCalculator(void);
    ~ExpressionCalculator(void);
 
    double f1(double a, double b, double c, double d);
    double f2(double a, double b, double c, double d);
    double f3(double a, double b, double c, double d);
 
    double Calculate(double a, double b, double c, double d);
 
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "ExpressionCalculator.h"
 
CalculatingError::CalculatingError(Errors error)
{
    _error = error;
}
void CalculatingError::RaiseError()
{
    switch(_error)
    {
    case Errors::DivBy0:
        DivBy0();
        break;
    case Errors::Negative:
        Negative();
        break;
    case Errors::InvalidLgArgument:
        InvalidLgArgument();
        break;
    }
}
CalculatingError::~CalculatingError()
{
 
}
void CalculatingError::Negative()
{
    std::cout << "Negative number in sqrt function" << std::endl;
}
void CalculatingError::DivBy0()
{
        std::cout << "Divide by zero" << std::endl;
}
void CalculatingError::InvalidLgArgument()
{
std::cout << "Invalid x in lg(x)" << std::endl;
}
 
 
 
ExpressionCalculator::ExpressionCalculator(void)
{
 
}
ExpressionCalculator::~ExpressionCalculator(void)
{
 
}
double ExpressionCalculator::f1(double a, double b, double c, double d)
{
    f = &ExpressionCalculator::f1;
    double tmp;
    try
    {
        if (a < 0) throw CalculatingError(Errors::Negative);
        if (!(a / 4 - b)) throw CalculatingError(Errors::DivBy0);
        tmp = (2 * c - d + sqrt(23 * a)) / (a / 4 - b);
    }
    catch (CalculatingError ce)
    {
        ce.RaiseError();
    }
    return tmp;
}
double ExpressionCalculator::f2(double a, double b, double c, double d)
{
    f = &ExpressionCalculator::f2;
    double tmp;
    try
    {
        if (c < 0) throw CalculatingError(Errors::Negative);
        if (!(b - a / 2)) throw CalculatingError(Errors::DivBy0); 
        tmp = (c + 4 * d - sqrt(123 * c)) / (b - a / 2);
    }
    catch (CalculatingError ce)
    {
        ce.RaiseError();
    }
    return tmp;
}
double ExpressionCalculator::f3(double a, double b, double c, double d)
{
    f = &ExpressionCalculator::f3;
    double tmp;
    try
    {
        if ((c - 5) < 0 || (c - 5) == 1) throw CalculatingError(Errors::InvalidLgArgument);
        if (!d) throw CalculatingError(Errors::DivBy0);
        if (!(a - b)) throw CalculatingError(Errors::DivBy0);
        tmp = (4 * log(c - 5) - 2 * d + 23) / (a - b);
    }
    catch (CalculatingError ce)
    {
        ce.RaiseError();
    }
    return tmp;
}
 
double ExpressionCalculator::Calculate(double a, double b, double c, double d)
{
    double tmp = &f(a,b,c,d);
    return 0;
}
0
Bers
Заблокирован
07.11.2011, 00:23 #7
не вижу точки входа в программу
0
atomohod
20 / 20 / 1
Регистрация: 01.04.2010
Сообщений: 57
07.11.2011, 00:30  [ТС] #8
вся прога большая. это отдельный класс. в методе main() просто создается экземпляр этого класса. код просто не компилируется
0
Bers
Заблокирован
07.11.2011, 00:39 #9
Цитата Сообщение от atomohod Посмотреть сообщение
вся прога большая. это отдельный класс. в методе main() просто создается экземпляр этого класса. код просто не компилируется
Я понимаю, смысл в том, что бы я мог скопипастить, и скомпилить у себя. А потом уже разбираться, что не так.

Мне нужно знать точно, как класс предполагается использовать. И проще будит спросить у автора пример кода с использованием, чем самому догонять как должно работать нечто, что даже не компилируется.

Поэтому, сделайте так: откройте отдельный мини-проектик. Перенесите в этот проектик только то, что относится к делу. Выложите сдесь.

Будим тестировать и выяснять. Желательно, если код будут сопровождать комментарии (что бы было понятно сразу, что делают методы классов, и зачем эти классы вообще нужны)
1
atomohod
20 / 20 / 1
Регистрация: 01.04.2010
Сообщений: 57
07.11.2011, 00:59  [ТС] #10
Спасибо огромное!

Проэкт и задание в attach'e.

Из задание (что в pdf) этот проэкт относится к 7му пункту (на 5й странице pdf'ки).
0
Вложения
Тип файла: zip exceptions.zip (5.82 Мб, 8 просмотров)
Bers
Заблокирован
07.11.2011, 01:23 #11
atomohod , мне нужны три файла:

1. ExpressionCalculator.h //тестируемый класс
2. ExpressionCalculator.cpp //реализация класса
3. main.cpp //здесь не должно быть ничего лишнего. Только пример работы тестируемого класса, иллюстрирующий неполадку.


Мне не нужен весь проект целиком. Мне не нужен main.cpp с километровой простыней кода.
Мне не нужны студийные файлы, тем более, что у меня нет студии, с помощью которой я смог бы открыть солюшен.

Мне нужны только три файла.
0
atomohod
20 / 20 / 1
Регистрация: 01.04.2010
Сообщений: 57
07.11.2011, 01:35  [ТС] #12
есть такое дело =)
0
Вложения
Тип файла: zip exc.zip (1.6 Кб, 7 просмотров)
Bers
Заблокирован
07.11.2011, 02:03 #13
atomohod, о том, какие роли выполняют классы, и что означают из методы аля f1(), f2() - это пусть каждый сам догадывается, да?


Ладно... итак...


C++
1
2
3
4
5
double ExpressionCalculator::Calculate(double a, double b, double c, double d)
{
    double tmp = &f(a,b,c,d); //чего автор хотел добиться этой строчкой?
    return 0;
}
0
atomohod
20 / 20 / 1
Регистрация: 01.04.2010
Сообщений: 57
07.11.2011, 02:08  [ТС] #14
f1() и f2() это функции, которые в 7 задании в пдф.

я хотел, получить значение функции, которая была вызвана последней для данного объекта, передав ей соответсвующие значения a, b, c, d.

т.е. создав объект ExpressionCalculator и вызваз у него f1() например, указатель *f указывает на эту функцию, которая была вызвана, и потом, вызвав метод Calculate(...) я могу не зная то какая функция вызывалась последней, получить нужное значение.

я только учусь, и возможно это можно сделать проще и логичней. В этом проекте я просто разбираюсь с callback
0
Bers
Заблокирован
07.11.2011, 05:47 #15
Честно говоря, я так и не понял, что за проблема такая. Мне самому интересно разобраться.
Я локализировал проблему:


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class CTest
{
    typedef void( CTest::*ptrFunc)(int Val);    
public:
    CTest() {  myfunc = &CTest::Test;  }
    
    void Start(int Val) { myfunc(Val);  } //error C2064: результатом вычисления 
                                                   //фрагмента не является функция, 
                                                   //принимающая 1 аргументов
private:
    void Test(int Val)    {  std::cout<< "Val = "<<Val<<std::endl;    }
    ptrFunc myfunc;
};
 
 
int main (void)
{
    CTest test;
    test.Start(30); 
 
    EndProgramm();
}
Добавлено через 21 минуту
дальнейший анализ проблемы:

Этот код уже компилируется:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//вынес имя указателя на функцию-метод за пределы класса, 
//что бы можно было создавать указатель за пределами класса
class CTest;
typedef void( CTest::*ptrFunc)(int Val);    
                                                            
 
class CTest
{
public:
    //инициализация указателя для тестов
    CTest() {  myfunc = &CTest::Test;  } 
    
   //пример того, как запустить метод класса для объекта изнутри класса
    void Start(int Val)   {  (this->*myfunc)(Val);                 }   
 
    //этот метод должен быть по итогу запущен
    void Test(int Val)    {  std::cout<< "Val = "<<Val<<std::endl; } 
private:
 
    //объявление указателя на метод в качестве данных-членов
    ptrFunc myfunc;  
};
 
 
int main (void)
{
    CTest test;
 
    //пример объявления указателя на функцию-метод извне класса
    ptrFunc myPtr=&CTest::Test; 
   
    //пример запуска метода на который указывает указатель извне класса
    (test.*myPtr)(10);   
 
 
    //этот метод запустит метод на который указывает указатель изнутри класса
    test.Start(30);  
 
    return 0;
}
Добавлено через 8 минут
Ну вроде разобрался более менее. Сейчас буду заводить код Топик-Стартера.
Должен будит хотя б скомпилироваться. Но подозреваю, что там помимо паленного синтаксиса есть ещё один серьёзный фейл

Добавлено через 38 минут
Обрати внимание, как я объявил указатель на метод класса.
Я использовал typedef что бы улучшить читабельность кода

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class ExpressionCalculator
{
public:
    ExpressionCalculator(void);
    ~ExpressionCalculator(void);
 
    double f1(double a, double b, double c, double d);
    double f2(double a, double b, double c, double d);
    double f3(double a, double b, double c, double d);
 
    double test(double a) { return 0;}
    double Calculate(double a, double b, double c, double d);
private:
    typedef double (ExpressionCalculator::*ptrFunc)(double a,double b,double c,double d);
 
    ptrFunc f; //так же нагляднее и понятнее объявлять указатель?
 
    //double(ExpressionCalculator::*f)(double,double,double,double);
};
Далее сам метод (исправлен, все компилируется)

C++
1
2
3
4
5
double ExpressionCalculator::Calculate(double a, double b, double c, double d)
{
    double tmp= (this->*f)(a,b,c,d);
    return tmp;
}
Здесь происходит следующее:
1. Идёт обращение к указателю, который указывает на метод класса
2. Запускается этот метод класса для объекта, на который указывает this
3. И результат работы этого метода записывается в переменную tmp

Собака была зарыта в том, что не_статический метод класса не может быть запущен сам по себе.
Он всегда запускается для какого то конкретного экземпляра класса.
И нужно компилятору обязательно знать this объекта, для которого сработает метод, на который указывает указатель.

Добавлено через 22 минуты
точнеее... все немножко иначе...

Когда мы хотим запустить не_статический метод класса, мы должны указатель компилятору для какого объекта мы его запускаем. Например:

ptrObj -> Method();

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

Указатель на метод класса содержит указатель на сам метод, но не знает, для какого именно из объектов этот метод нужно запустить.

*ptrFunc(); // эта запись эквивалентна вызову Method(); для класса. Но компилятору нужно знать для какого объекта метод запускается!

(ptrObj->*ptrFunc)(); //эквивалентна ptrObj -> Method();

Читать её нужно так: Для объекта, на который указывает ptrObj, запустить метод на который указывает ptrFunc, с аргументами, которые стоят в скобках. (в моём примере там ничего не стоит)

Добавлено через 28 минут
Можно ещё глубже проанализировать эту картинку:

допустим мы хотим объявить указатель на обычную функцию:
C++
1
2
3
4
5
6
7
8
9
10
void Foo() { std::cout << "YES!\n";}  //наш подопытный кролик
typedef void (*myPtr)();   //псевдоним для улучшенной читабельности
 
int main()
{
    myPtr test;  //создадим указатель на функцию
    test=&Foo;    //присвоим указателю значение функции
    (*test)();      //запустим на выполнение функцию, на которую указывает указатель
    return 0;
}

Из примера видно, что запись (*test)();
Компилятор заменит на Foo();

То бишь, в качестве имени функции будит выступать значение указателя, а то что в скобочках так и останется

Что происходит с указателем_на_метод класса?
Абсолютно тоже самое! Вместо указателя_на_метод компилятор подставит имя реального метода, скормив ему те же самые аргументы.

Проблема в том, что не_статический метод класса сам по себе вызвать нельзя. Компилятор должен знать для какого объекта он его вызывает.

Поэтому в записи:

(Объект.*Указатель)() компилятор сначала *Указатель подменит на реальное имя метода класса

Получится (Объект.Метод)()

Если же объект не указать - будит ошибка компиляции.

Исходя из всего выше изложенного можно сделать удивительный вывод.
Оказывается, запись: (Объект.Метод)(); работает!!!

Этот код компилируется:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Ctest
{
public:  void Foo() { std::cout << "YES!\n";}
};
 
int main()
{
    Ctest test;
    
    test.Foo(); //все нормальные люди пишут так
    (test.Foo)(); //оказывается, так писать тоже можно
 
    return 0;
}
/зы не жалею что потратил на этот новый для меня материал несколько часов. Хотя пришлось мало-мало погуглить-шмуглить и отфильтровать кучу хлама.

/зыы Уважаемые модераторы, ваш форум жосско глючит этой ночью. Вот, шоб вы знали.

Добавлено через 19 минут
Цитата Сообщение от atomohod Посмотреть сообщение
C++
1
double tmp = fn(a,b,c,d);
получаю при компиляции

error C2064: результатом вычисления фрагмента не является функция, принимающая 4 аргументов
подскажите, что не так?
Подозреваю, что результатом вычисления фрагмента является функция, принимающая 5 аргуметов! И этот пятый аргумент - это указатель this
Интересно, а можно как нибудь его так подсунуть функции, прям в качестве аргумента этой функции?

Сейчас попробую...

Добавлено через 7 минут
Нет... напрямую закатать this в сам аргумент функции не получилось. Фокус не прошёл. Компилятор на такое сразу нафег послал.
2
07.11.2011, 05:47
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.11.2011, 05:47
Привет! Вот еще темы с ответами:

Нужна помощь по алгоритму - C++
Подскажите литературу, где можно найти алгоритм поиска всех простых циклов в графе граф задан матрицей смежности. Сам использую поиск в...

нужна помощь с рекурсией. - C++
Ребята, кто мне может объяснить доступно рекурсию на элементарном примере? в интернетах в основном примеры с факториалом. вроде с ним...

find_if, нужна помощь - C++
Здравствуйте! Помогите решить проблему пожалуйста. Тут все просто, но у меня куча ошибок ( Вот структура struct HardWare { ...

Нужна помощь с программой - C++
Добрый день!! Помогите пожалуйста с программой, задача состоит в следующем: Все задания выполняются с использованием классов. ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Закрытая тема Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru