C++ 理解复杂的typedef表达式

C++ 理解复杂的typedef表达式,c++,c++11,C++,C++11,我想知道这个表达是什么意思 typedef bool (*compareShapes)(const Shape* s1, const Shape* s2); Shape是一个类。compareShapes是函数指针的别名,它接受2const Shape*并返回bool compareShapes func = [] (const Shape* s1, const Shape* s2) -> bool { return *s1 == *s2; //something boolean

我想知道这个表达是什么意思

typedef bool (*compareShapes)(const Shape* s1, const Shape* s2);

Shape
是一个类。

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,因此有两部分-类型和为其定义的新名称

第一部分是类型:

bool (*)(const Shape* s1, const Shape* s2);
它是一个指向函数的指针,取两个指向常量形状参数的指针,并返回bool

第二部分是类型的名称:
compareShapes
。诚然,函数指针typedef很难读取,但这部分是因为函数指针语法并不经常使用

例如,我可以编写任意数量的兼容函数:

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
编写非模板函数可能更常见,这比原始函数指针更灵活


C没有(和早期版本的C++没有)这些设施,所以必须使用函数指针。我怀疑它们主要用于与旧代码的向后兼容性,也可能用于资源受限的环境中。

要在注释中添加一些细节:

这是一个函数指针。typedef的存在使其更易于使用。通常,typedef的格式为“typedef实际类型new\u名称”。例:


显然,这条线在实践中永远不会出现。但是对于更复杂的类型(特别是那些涉及指针和模板的类型),使用typedef可以使代码更具可读性

此表达式将函数指针类型命名为“compareShapes”。在本例中,该类型是一个函数,它接受指向两个形状对象的指针并返回布尔值。这样,将函数分配给指针并调用它的代码就更加清晰了

下面是一个可能在实践中出现的示例。假设形状至少有两个字段:周长和面积。用户可能希望对其中一个进行排序:

#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;
}
#包括
布尔周界比较(常数形状*a,常数形状*b){
返回一个->周界;
}
布尔区域比较(常数形状*a,常数形状*b){
返回一个->区域;
}
//请注意CompareShapes的大小写,以显示它是一个类型,而不是一个变量
typedef bool(*比较图形)(常量形状*a,常量形状*b);
无效排序形状(标准::向量和形状,比较形状比较){
//惰性编程:冒泡排序
对于(int first=0;firstcout您应该使用using语句。它使相同的声明更易于阅读:

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  -----^------------------------------^
//函数指针类型--v--------------------------------------------v
使用compareShapes=std::add_pointer_t;
//函数签名-----^------------------------------^
函数签名的组成如下所示:

<return-type>( <arguments...> )
<return-type>(*)( <arguments...> )
()
当您在其中添加指针时,它如下所示:

<return-type>( <arguments...> )
<return-type>(*)( <arguments...> )
(*)()
如果在此处添加指针名称或类型名称,请将其添加到星号之后:

<return-type>(*typeOrPointerName)( <arguments...> )
(*typeOrPointerName)()

compareShapes
是一个函数指针,它采用2个类型参数(指向
形状的指针)并返回布尔值

您可以分配
compareShapes
任何适合此签名的函数

那么比如说,

bool isShapesValid(const Shape* s1, const Shape* s2) 
可以分配:

compareShapes objCompareShapes = &isShapesValid;

您可以使用
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
声明为指向函数的指针(指向常量
Shape
,指向常量
Shape
)返回
bool

compareShapes func = [] (const Shape* s1, const Shape* s2) -> bool {
    return *s1 == *s2; //something boolean
};
bool result = func(s1, s2);

compareShapes
是一个比较两个形状对象的函数原型(签名)

例如:

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.
}

它不是
*compareShapes
?在这种情况下,它是一个函数指针typedef。看起来很像一个函数指针。这意味着任何一个函数,一个按值一个按指针,都可以分配给compareShapes。你可以用这种方法实现通用算法。有关使用这种方法的示例,请参见qsort。另一种方法是d是一个模板,请参阅std::sort以了解如何使用模板实现相同的想法您可能想知道为什么它是指向函数的指针的声明,而不是函数本身。原因是函数不能通过值传递和返回;您只能通过指向它的指针来实现。“很明显,这句话在实践中永远不会出现。”微软想要一句话