理解复杂的typedef表达式

You*_*oui 12 c++ c++11

我想知道这个表达意味着什么?

typedef bool (*compareShapes)(const Shape* s1, const Shape* s2);
Run Code Online (Sandbox Code Playgroud)

Shape是一堂课.

Gui*_*cot 25

您应该使用using语句.它使同样的声明更容易阅读:

using compareShapes = bool(*)(const Shape*, const Shape*);
Run Code Online (Sandbox Code Playgroud)

现在看?类型是在等号后面.它是指向函数类型的指针.

人们也可以这样声明:

// function pointer type --v----------------------------------------------------v
using compareShapes =      std::add_pointer_t< bool(const Shape*, const Shape*) >;
//                    function signature  -----^------------------------------^
Run Code Online (Sandbox Code Playgroud)

函数签名的组成如下:

<return-type>( <arguments...> )
Run Code Online (Sandbox Code Playgroud)

当您在其中添加指针时,它看起来像这样:

<return-type>(*)( <arguments...> )
Run Code Online (Sandbox Code Playgroud)

如果您在此处添加指针名称或类型名称,请在星标后添加:

<return-type>(*typeOrPointerName)( <arguments...> )
Run Code Online (Sandbox Code Playgroud)

  • 也许我是一个老屁,但我的反应是"天啊,不是另一种方式写出我现在必须记住的那个该死的东西". (6认同)
  • 虽然我喜欢"等待,但是有一种古老的方式?呃,这太丑了.很高兴新的方式存在" (5认同)
  • 也许我的观点不受欢迎,但在很多情况下我发现typedef更容易阅读,包括这个. (4认同)
  • 问题是"我正在阅读代码,发现了这个,它是什么?",为什么评价最高的答案"你应该这样做"?OO (2认同)

Use*_*ess 15

嗯,它是一个typedef,所以有两个部分 - 类型和为它定义的新名称.

第一部分是类型:

bool (*)(const Shape* s1, const Shape* s2);
Run Code Online (Sandbox Code Playgroud)

这是一个指向函数的指针,取两个指向const-Shape的参数,然后返回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);
Run Code Online (Sandbox Code Playgroud)

这告诉我是否a是相同的b,或完全的内部b,或是否ab具有相同数量的孔.

然后,我可以编写适用于任何比较的代码,并选择以后使用的代码,例如:

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
}
Run Code Online (Sandbox Code Playgroud)

现代代码中可能更常见的是编写模板,采用任意比较器类型(如std::sort),或编写非模板函数std::function<bool(const Shape*, const Shape*)>,这比原始函数指针更灵活.

C没有(并且早期版本的C++没有)具有这些功能,因此不得不使用函数指针.我怀疑它们主要用于与旧代码的向后兼容性,并且可能在资源受限的环境中.


Sta*_*ght 12

compareShapes是函数指针的别名,它接受2 const Shape*并返回bool

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

或者另一个例子,如果你已经有了功能:

bool someFunc(const Shape* s1, const Shape* s2) { return true; }
compareShapes funcPtr = someFunc;
bool result = funcPtr(s1, s2);
Run Code Online (Sandbox Code Playgroud)

有关函数指针的更多信息,请点击此处


And*_*rew 5

要在评论中添加一些细节:

这是一个函数指针.typedef可以让它更容易使用.通常,typedef的格式为"typedef actual_type new_easier_name".例如:

typedef int i
Run Code Online (Sandbox Code Playgroud)

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

该表达式将名称"compareShapes"赋予函数指针类型.在这种情况下,该类型是一个函数,它接收指向两个Shape对象的指针并返回一个布尔值.这样,将函数分配给指针并调用它的代码就更清楚了.

这是一个可能出现在实践中的例子.假设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;
}
Run Code Online (Sandbox Code Playgroud)

  • "显然这条线在实践中永远不会出现".MIcrosoft想和你一起使用WORD. (4认同)