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

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

Восстановить пароль Регистрация
Другие темы раздела
C++ Округлить любое вещественное число до определённого количества знаков с математической точностью http://www.cyberforum.ru/cpp-beginners/thread378871.html
Пишем Microsoft Visual Studio -> Win32 Console Application -> C++. Нужно написать функцию, которая округляет любое вещественное число до определённого количества знаков с математической точностью. Вот что уже готово, можете подсказать в чем ошибка и как исправить? (Изучаю функцию одну пару, так что хочу попросить объяснять и показывать как можно проще и примитивнее :) Про ceil нам тоже еще не...
C++ Помогите плиз модифицировать прогу Добрый вечер! Есть функция, переставляющая соседние слова в строке: #include "stdafx.h" #include <clocale> #include <iostream> #include <windows.h> using namespace std; http://www.cyberforum.ru/cpp-beginners/thread378868.html
Помогите со стеком.. C++
Смоделировать стек на базе статического массива по заданию. Написать основные операции для работы со стеком (push, pop, top, empty, full) . Для этого (если в задании не указан иной способ) в программе на входе задать последовательность из К (К> 10) целых чисел (числа вводить с клавиатуры). Все положительные числа последовательно заносить в стек, а каждое отрицательное число должно изымать из...
C++ Игра в камень,ножницы бумага.Что можно улучшить\оптимизировать?
// KamenNozhnicyBumaga.cpp: определяет точку входа для консольного приложения. // #include "stdafx.h" #include "time.h" #include "stdio.h" #include "stdlib.h" int _tmain(int argc, _TCHAR* argv)
C++ Простейший класс http://www.cyberforum.ru/cpp-beginners/thread378848.html
Разработать класс 1.Комплексное число 2. время 3. массив 4. дата 5. стек 6 строка 7. многочлен Любой из этих классов, очень буду благодарен!!!
C++ wchar_t что ето за тип данних: wchar_t скок у нему байт?? подробнее

Показать сообщение отдельно
Bers
Заблокирован
07.11.2011, 05:47     CALLBACK. Нужна помощь
Честно говоря, я так и не понял, что за проблема такая. Мне самому интересно разобраться.
Я локализировал проблему:


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 в сам аргумент функции не получилось. Фокус не прошёл. Компилятор на такое сразу нафег послал.
 
Текущее время: 23:10. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru