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

Ультиматум варнинга - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Передача значения переменной-члена из класса в функцию http://www.cyberforum.ru/cpp-beginners/thread450136.html
Добрый день, имеется класс: class ZernPole{ public: ZernPole(int Zerno) { zpZerno=Zerno; }; ~ZernPole() {}; int GetZerno() const { return zpZerno; }; void SetZerno(int Zerno) {zpZerno=Zerno;}; bool GetPosev() const { return zpPosev; }; void SetPosev(bool Posev) {zpPosev=Posev;};
C++ Статические члены Мне необходимо создать класс А, причем: этот класс всегда нужен в единственном экземпляре, через этот класс работают классы В и С (т.е. в них храниться указатель на А). Я решил сделать все поля данных и методы класса А статическими. Вопрос: каким образом это может повлиять на производительность программы? Класс А не является производным и не имеет наследников. http://www.cyberforum.ru/cpp-beginners/thread450131.html
Чтение файла построчно C++
Вот у меня есть файл "cmd.ini" в нем записан текст построчно и мне надо с каждой строкой выполнить это код "g_Engine.pfnAddCommand( line, NOP );" где 'line' это каждая строка файла. я пробывал так: fgets(line,200, fp); g_Engine.pfnAddCommand( line, NOP );
C++ Строка-палиндром
Подскажите пожайлуйста, как определить является ли строка палиндромом(можно использовать стандартные строковые подпрограммы) и как определить число слов в строке не используя строковые подпрограммы??? P.S. Очень срочно надо. Заранее спасибо! Добавлено через 18 минут Извините, нельзя использовать строковые подпрограммы
C++ Вызов функции по ссылке в C++ http://www.cyberforum.ru/cpp-beginners/thread450113.html
Привет форумчане. Возникла у меня такая проблем с решением задачи. Не могу сообразить как её сделать. Если несложно то помогите пожалуйста. Заранее спасибо. Задача 1: http://www.cyberforum.ru/attachment.php?attachmentid=128767&stc=1&d=1329812832
C++ Посчитать количество букв в строке мне надо посчитать количество букв в строки, помню была стандартая функция но не помню как называется. подробнее

Показать сообщение отдельно
ValeryLaptev
Эксперт С++
1039 / 818 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
21.02.2012, 14:10     Ультиматум варнинга
Вот для начала почитай.


Указатели на функции и указатели на методы

Есть еще одна, более важная причина, по которой нельзя считать нашу функцию-фильтр copy_if() достаточно универсальной: мы не можем передать функции-фильтру предикат-метод. Дело в том, что указатель на метод существенно отличается по типу от обычного указателя на функцию, даже если прототипы функции и метода внешне идентичны. Вспомним, как определяется указатель на функцию:
Javascript
1
тип (*имя-указателя)(список параметров);
Для сокращения записи применяют обычно оператор typedef. Следующее объявление вводит новое имя типа:
Javascript
1
typedef тип (*тип-указателя)(список параметров);
После этого указатель на функцию можно объявлять так:
Delphi
1
тип-указателя имя-указателя;
Указателю присваивается адрес функции. В С++ разрешается присваивать адрес функции явно или неявно задавая операцию получения адреса:
Delphi
1
2
имя-указателя = &имя-функции;
имя-указателя = имя-функции;
В последнем случае имя функции неявно преобразуется в адрес.
ПРИМЕЧАНИЕ
В системе Visual C++.NET 2003 для библиотечных функций работает только вариант с явной операцией адресации. Второй вариант вызвал фатальную ошибку компилятора fatal error 1001: INTERNAL COMPILER ERROR. Borland C++ Builder 6 оба вызова обрабатывает правильно.

Вызов функции через указатель выполняется так:
Javascript
1
(*имя-указателя)(аргументы);
Тот же вызов можно написать в более простой форме:
и
Javascript
1
мя-указателя(аргументы);
Рассмотрим несколько простых примеров. Допустим, у нас объявлен указатель на функцию:
Javascript
1
int (*pf)(void);
Этому указателю можно присвоить адрес любой функции с таким же прототипом, в том числе и библиотечной. Например, такой прототип имеет функция-генератор случайного числа rand(), который объявлен в заголовке библиотеки <cstdlib>:
Javascript
1
2
3
4
5
int f1(void) { return 1; } 
int f2(void) { return 2; }
pf = f1;    cout << pf() << endl;                // вызов f1()
pf = f2;    cout << pf() << endl;                // вызов f2()
pf = &rand; cout << pf() << endl;                // вызов rand()
Напишем теперь простой класс
Javascript
1
2
3
4
5
6
class Constant
{    int value;
   public: 
    Constant(const int &a): value(a) {}
    int get(void) { return value; }
};
Метод get() с виду имеет тот же прототип, что и функции в приведенном ранее фрагменте. Однако попытки присвоить адрес метода get() указателю pf компилятор пресекает «на корню». Да и не совсем понятно, как этот адрес задавать. Вариантов два.
  1. Объявить объект и взять адрес метода в объекте:
    Constant A(5); pf = &A.get();
  2. Не объявлять объект, а приписать префикс класса:
    pf = &Constant::get;
Первый вариант вообще неверный: и Visual C++.NET 2003, и Borland C++ Builder 6 сообщают, что операцию взятия адреса & так использовать нельзя. Второй вариант — ближе к истине: оба компилятора сообщают только о невозможности выполнить преобразование типов. Попытки прописать преобразование явно не проходят:
Javascript
1
2
3
pf = static_cast<int (*)(void)>(&Constant::get);
pf = reinterpret_cast<int (*)(void)>(&Constant::get); 
pf = (int (*)(void))(&Constant::get);
Все эти варианты вызывают ту же ошибку компиляции — невозможность преобразования типов. Таким образом, тип указателя на метод класса кардинально отличается от типа указателя на функцию: адрес метода нельзя присвоить указателю на функцию, даже если внешне их прототипы совпадают.
Это становится понятным, если мы вспомнить, что нестатические методы получают дополнительный параметр — указатель this.

Аналогично, нельзя присвоить обычному указателю на функцию адрес виртуального метода — в этом случае дело усугубляется еще наличием в составе объекта указателя на таблицу виртуальных методов. А вот со статическими методами картина другая! Статический метод не получает никаких «лишних параметров», поэтому его адрес можно присваивать обычному указателю на функцию без всяких преобразований. Добавим в класс Constant статическое поле и статический метод с нужным нам прототипом:
Javascript
1
2
3
4
5
6
7
8
class Constant
{    int value;
    static int d;
public: 
    Constant(const int &a): value(a) {}
    int get(void) { return value; }
    static int getd(void) { return d; }                // статический метод
};
Тогда нашему указателю pf можно присвоить адрес статического метода согласно второму из приведенных ранее вариантов, например:
Javascript
1
pf = Constant::getd;        // или pf = &Constant::getd;
Префикс, естественно, необходимо писать.
Указатель на метод объявляется по-другому (см. п.п. 8.3.3 в [1]) — нужно задать имя класса в качестве префикса:
Javascript
1
int (Constant::*pm)(void);
Такому указателю можно присваивать адреса обычных и виртуальных методов согласно второму из приведенных ранее вариантов, например:
Javascript
1
pm = &Constant::get;        // или pm = Constant::get;
Адрес статического метода, так же как и адрес обычной функции, такому указателю присвоить нельзя — возникает ошибка трансляции: компилятор сообщает о невозможности выполнить преобразование типов.
И косвенный вызов метода выполняется по-другому — с помощью операции выбора члена класса .* или ->* (см. п. 5.5 в [1]). Несмотря на то, что указатель на член класса является отдельной независимой от класса переменной, вызов метода по указателю возможен только при наличии объекта, например:
Javascript
1
2
Constant A(5);
cout << (A.*pm)() << endl;
Выражение(A.*pm)() означает следующее: для объекта A вызвать метод, чей адрес записан в указателе pm. Слева от операции .* — объект, справа — указатель на метод. Скобки вокруг выражения A.*pm писать обязательно, так как приоритет операции вызова функции (()) выше, чем приоритет операции выбора члена класса (.*).
В выражении (объект.*указатель) можно заменить часть объект. записью указатель->, например:
Javascript
1
2
Constant *pc = new Constant(7);
cout << (pc->*pm)() << endl;
Обратите внимание: в выражении (pc->*pm) слева — обычный указатель на динамический объект, а справа — указатель на метод этого объекта. Это два совершенно разных типа указателя.
Интересно, что в Visual C++.NET 2003 размер sizeof(pf) указателя на функцию совпадает с размером sizeof(pm) указателя на член класса и равен 4 байта. А вот система Borland C++ Builder 6 выдает совершенно разные цифры: размер указателя на функцию равен 4 байта, а размер указателя на метод — 12 байт!

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