Я хотел бы знать, что означает это выражение?
typedef bool (*compareShapes)(const Shape* s1, const Shape* s2);
Shape
- класс.
Я хотел бы знать, что означает это выражение?
typedef bool (*compareShapes)(const Shape* s1, const Shape* s2);
Shape
- класс.
Вы должны использовать использование-операторов. Это облегчает чтение той же декларации:
using compareShapes = bool(*)(const Shape*, const Shape*);
Увидимся сейчас? тип после знака равенства. Это указатель на тип функции.
Можно также объявить это так:
// function pointer type --v----------------------------------------------------v
using compareShapes = std::add_pointer_t< bool(const Shape*, const Shape*) >;
// function signature -----^------------------------------^
Подпись функции складывается следующим образом:
<return-type>( <arguments...> )
Когда вы добавляете в него указатель, он выглядит так:
<return-type>(*)( <arguments...> )
И если вы добавили имя указателя или имя типа здесь, добавьте его после звезды:
<return-type>(*typeOrPointerName)( <arguments...> )
Ну, это typedef, поэтому есть две части - тип и новое имя, определяемое для него.
Первая часть - это тип:
bool (*)(const Shape* s1, const Shape* s2);
который является указателем на функцию, беря два аргумента указателя на константу и возвращает bool.
Вторая часть - это имя типа: compareShapes
. По правде говоря, функции typedefs указателя функции сложны для чтения, но это частично только потому, что синтаксис указателя функции не используется очень часто.
Так, например, я могу написать любое количество совместимых функций:
bool identical(const Shape *a, const Shape *b);
bool strictlyContained(const Shape *a, const Shape *b);
bool topologicallyEquivalent(const Shape *a, const Shape *b);
который говорит мне, является ли a
идентичным b
или целиком внутри b
, или a
и b
имеют одинаковое количество отверстий.
Затем я могу написать код, который работает с любым сравнением, и выбрать, что использовать позже, например:
compareShapes cmp;
if (shouldUseIdentityComparison()) {
cmp = &identical;
} else if (shouldUseInsideComparison()) {
cmp = &strictlyContained;
} else {
cmp = &topologicallyEquivalent;
// ...
if (cmp(a,b)) {
// they're equal, for whichever comparison we chose above
}
В современном коде более вероятно, что либо пишут шаблон, беря произвольный тип компаратора (как в std::sort
), либо записывая функцию без шаблона, принимающую std::function<bool(const Shape*, const Shape*)>
, которая более гибкая, чем сырая функция указатель.
C не использует (и более ранние версии С++) эти средства, поэтому пришлось использовать указатели на функции. Я подозреваю, что они в основном используются для обратной совместимости со старым кодом и, возможно, в средах с ограниченными ресурсами.
compareShapes - это псевдоним для указателя функции, который принимает 2 const Shape*
и возвращает bool
compareShapes func = [] (const Shape* s1, const Shape* s2) -> bool {
return *s1 == *s2; //something boolean
};
bool result = func(s1, s2);
Или другой пример, если у вас уже есть функция:
bool someFunc(const Shape* s1, const Shape* s2) { return true; }
compareShapes funcPtr = someFunc;
bool result = funcPtr(s1, s2);
Подробнее о указателях функций доступно ЗДЕСЬ
Чтобы добавить некоторые комментарии к комментариям:
Это указатель на функцию. Здесь используется typedef, чтобы упростить его использование. Обычно typedefs имеют форму "typedef actual_type new_easier_name". Пример:
typedef int i
Очевидно, что эта линия никогда не появится на практике. Но для более сложных типов (особенно с указателями и шаблонами) использование typedef может сделать ваш код более читаемым.
Это выражение дает имя "compareShapes" для типа указателя функции. В этом случае этот тип является функцией, которая принимает указатели на два объекта Shape и возвращает логическое значение. Таким образом, код, назначающий функцию указателю и вызывающий его, намного понятнее.
Вот пример, который может появиться на практике. Предположим, что у формы есть как минимум два поля: периметр и область. Пользователь может захотеть сортировать по любому из них:
#include <vector>
bool perimeterComparison(const Shape* a, const Shape* b){
return a->perimeter <= b->perimeter;
}
bool areaComparison(const Shape* a, const Shape* b){
return a->area <= b->area;
}
//Note the capitalization of CompareShapes to show it is a type, not a variable
typedef bool (*CompareShapes)(const Shape* a, const Shape* b);
void sortShapes(std::vector<Shape*>& shapes, CompareShapes comparison){
//Lazy programming: bubble sort
for(int first = 0; first < shapes.length(); shapes++){
for(int second = first + 1; second < shapes.length(); shapes++){
if(!comparison(shapes[first], shapes[second])){
Shape* temp = shapes[second];
shapes[second] = shapes[first];
shapes[first] = shapes[second];
}
}
}
}
int main(){
//This could just as easily point to perimeterComparison or something else valid
CompareShapes compareFunction = &areaComparison;
std::vector<Shape*> shapes(10);
for(int i = 0; i < 10; i++){
shapes[i] = new Shape(); //Initialize the shapes somehow
}
sortShapes(shapes, compareFunction);
for(int i = 0; i < 10; i++){
cout << shapes[i] << "\n";
}
return 0;
}
Вы можете использовать cdecl
для интерпретации таких типов, но вам нужно вставить struct
перед именами классов и заменить bool
, чтобы он разбирался как код C:
cdecl> explain struct bool (*compareShapes)(const struct Shape* , const struct Shape* )
declare compareShapes as pointer to function (pointer to const struct Shape, pointer to const struct Shape) returning struct bool
Затем вам нужно мысленно отменить это преобразование, указав
объявить
compareShapes
как указатель на функцию (указатель на constShape
, указатель на constShape
), возвращающийbool
compareShapes
- это указатель на функцию, который принимает 2 параметра типа (указатель на Shape
) и возвращает логическое значение.
Вы можете назначить compareShapes
любую функцию, которая соответствует этой сигнатуре.
Итак, например,
bool isShapesValid(const Shape* s1, const Shape* s2)
может быть назначен:
compareShapes objCompareShapes = &isShapesValid;
typedef bool (*compareShapes)(const Shape* s1, const Shape* s2);
bool CmpShapes(const Shape *s1,const Shape *s2){retunr true;}
compareShapes
- это прототип функции (подпись), который сравнивает два объекта Shape
например:
class Shape{};
class CTest{
compareShapes m_cmp;
public:
CTest(compareShapes _cmpFunc):m_cmp(_cmpFunc){
printf("m_cmp: %p %s\n",m_cmp,m_cmp(NULL,NULL)?"true":"false");
};
};
void main(){
Ctest tst(&CmpShapes);//we pass CmpShapes address.
}