Московский государственный университет имени М.В.Ломоносова
Опубликован: 01.11.2004 | Доступ: свободный | Студентов: 11275 / 456 | Оценка: 4.12 / 4.01 | Длительность: 19:20:00
ISBN: 978-5-9556-0077-9
Специальности: Программист
Лекция 11:

C++: методы-члены класса, дружественные классы и члены класса

< Лекция 10 || Лекция 11: 123 || Лекция 12 >

Методы с переменным числом параметров

Метод может иметь переменное число параметров: это указывается в конце списка параметров символом многоточия ... . Методы с переменным числом параметров должны иметь как минимум один описанный формальный параметр.

Для применения переменного числа параметров можно использовать:

  • макрос va_start(указатель_списка_параметров,последний_параметр) - при инициализации указателя и установке его на начало переменного списка параметров;
  • макрос va_arg(указатель_списка_параметров,i) - при выборе параметра и продвижении указателя в соответствии с его типом на следующий параметр;
  • макрос va_end(указатель_списка_параметров) - при установке указателя на список параметров, равный null, после извлечения значений всех параметров;
  • тип va_list - для создания указателя на список параметров.

Например:

#include <stdio.h>   
    // Библиотека, содержащая тип va_list
#include <varargs.h>
#include <iostream>
int Fx ( int i1, ... ); 
    // Прототип Функции с переменным 
    // числом параметров
void main( void )
{   // Вызов функции Fx с различным 
    // числом параметров
std::cout<< Fx ( 100, 200) );
std::cout<< Fx ( 5 ) );
std::cout<< Fx ( -1,-3,45 ) );
}
int Fx ( int i1, ... )  
    // Реализация функции с переменным 
    // числом параметров
{  int sumx,i;
   sumx = 0; i = i1;  
   va_list list1;        
       // Список параметров
   va_start(list1, i1 ); 
       // Инициализация списка параметров
   while( i != -1 )   {
      sumx += i;
      i = va_arg(list1, int);
      //Извлечение следующего параметра
   }
   va_end(list1);      
   return( sumx );
}

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

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

Объявление указателя на метод может иметь следующее формальное описание:

тип_метода (имя_класса::*имя_метода_указателя)
    (список параметров);
тип_функции (*имя_ функции_указателя)
    (список параметров);

Инициализация указателя может иметь следующее формальное описание:

тип_метода имя_класса::*имя_метода_указателя
    (список параметров)=
    &имя_класса::имя_любого_метода;
тип_функции (*имя_ функции_указателя)
    (список параметров)= &имя_функции;

Вызов метода, объявленного как указатель на метод, может быть выполнен следующим образом:

(имя_объекта->*имя_ метода_указателя)
    (список параметров);
(*имя_ функции_указателя)(список параметров);

Для функций, но не для методов - членов класса, разрешена другая форма вызова метода:

имя_ функции_указателя(список параметров);
(имя_ функции_указателя)(список параметров);

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

тип_метода имя_метода (тип_метода_указателя
    (*имя_метода_указателя)
	(список параметров));

Вызов метода, использующего в качестве параметра указатель на метод, может иметь следующее формальное описание:

имя_метода(имя_объекта->*имя_метода_указателя);
имя_функции(имя_функции_указателя);

Разрешается создавать массив указателей на функции.

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

Например:

class a1
{
public:
    a1(void);
    ~a1(void);
    int Fx1(int i1);
    int Fx2(int i2);
};
a1::a1(void){}
a1::~a1(void){}
int a1::Fx1(int i1){    return 1;}
int a1::Fx2(int i2){    return 2;}

int (*Fy_pointer)();  
    // Объявление указателя на функцию
int Fy ();
int _main(int argc, char* argv[])
{  
     a1* a1Object = new a1();
 int (a1::*Fx_pointer)(int)=&a1::Fx2;  
    // Объявление и инициализация указателя
    // на метод - член класса
    int i;
    i=(a1Object->*Fx_pointer)(1);  
    // Вызов по указателю на метод
   std::cout<<i;
   int (*Fy_pointer)()=&Fy;          
   // Объявление и инициализация указателя
   // на функцию
   std::cout<<(Fy_pointer)();   
   std::cout<<(*Fy_pointer)();  
   // Вызов по указателю на 
   // функцию (две формы)
    return 0;
}
int Fy ()  {return 5;}

Встроенные функции

Встроенные функции указываются оператором inline. Применение встроенных функций может несколько сократить время выполнения программы, так как компилятор встраивает код такой функции в том месте программы, где указан ее вызов.

Например:

inline void Fx(void) { 
    std::cout<<"Функция Fx"<<std::endl;}
...
Fx(void); 
    // Этот код  будет заменен компилятором
    // на код встроенной функции

Перегрузка функций и методов

Язык C++ позволяет выполнять перегрузку функций и методов - членов класса, то есть вызывать функцию (метод) с тем же именем, но с различными типами фактических параметров. Для создания перегружаемой функции следует указать отдельный прототип и сделать отдельное объявление для каждого списка параметров. Если функции различаются только типом и имеют совпадающие списки параметров, то для таких функций перегрузка не допускается.

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

< Лекция 10 || Лекция 11: 123 || Лекция 12 >
Александр Демьяненко
Александр Демьяненко

Можно ли сдавать один и тот же тест несколько раз?
Или же один и тот же тест можно сдать лишь однажды?

Максим Стогний
Максим Стогний

Добрый день!

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

тип_метода (имя_класса::*имя_метода_указателя)
    (список параметров);
тип_функции (*имя_ функции_указателя)
    (список параметров);

при этом можно было  тип_функции во втором описании заменить на тип_метода? Т.е.:

тип_метода (*имя_ метода_указателя)
    (список параметров);