指向采用抽象参数的函数的指针
Pointer to function taking abstract parameter
设 A 为 C++ 中的抽象 class:
// legal
class A {
virtual void m() = 0;
}
定义抽象类型的变量当然是非法的class:
A a; // illegal
确实如此,clang
3.6.0 抱怨:
wat.cc:5:3: error: variable type 'A' is an abstract class
A a;
^
wat.cc:2:16: note: unimplemented pure virtual method 'm' in 'A'
virtual void m() = 0;
^
1 error generated.
同样,用抽象类型的参数定义函数也是非法的class:
void f(A a) {} // illegal
的确,clang
抱怨道:
wat.cc:5:10: error: parameter type 'A' is an abstract class
void f(A a) {}
^
wat.cc:2:16: note: unimplemented pure virtual method 'm' in 'A'
virtual void m() = 0;
^
1 error generated.
另一方面,定义一个类型为指向抽象值指针的变量当然是合法的 class:
A * a_ptr; // legal
即使 class 从未定义任何基础 class,类型 A *
至少有一个值,nullptr
,因此总是可以以类型正确的方式使用这样的变量,即使它可能不是很有用,除非 A
在某些时候得到一些具体的 subclasses:
a_ptr = nullptr; // legal
大概,这个推理适用于任何指针类型。
同样,定义一个接受参数的函数是合法的,该参数的类型是指向抽象值的指针class:
void f(A * a) {} // legal
同样,定义一个接受参数的函数是合法的,该参数的类型是指向函数的指针,该函数接受的参数类型是指向抽象值的指针class:
void f(void (* g)(A *)) {} // legal
这两个函数当然可以合法调用:
f(nullptr); // legal
据推测,函数参数的具体类型与类型的正确性无关,只要是指针类型即可。在任何一种情况下,对 f
的调用都应该是合法的。就类型论而言,格式良好的指针类型始终是合法的,并且 nullptr
始终存在于其中。根据这个推理,这个定义应该被推定为合法的:
void f(void (* g)(A)) {}
f
是一个接受参数的函数,该参数的类型是指向函数的指针,该函数接受的参数类型是抽象值 class A.
事实上,该参数的唯一可能值是 nullptr
,因为没有实际函数可以采用抽象类型的参数 class。
这符合 C++ 标准吗?
Clang 抱怨:
wat.cc:5:20: error: parameter type 'A' is an abstract class
void f(void (* g)(A)) {}
^
wat.cc:2:16: note: unimplemented pure virtual method 'm' in 'A'
virtual void m() = 0;
^
1 error generated.
GCC 没有。
更新:这个问题回答正确,但问题本身在声明 Clang 接受该功能时是错误的。 GCC 和 Clang 都会在这段代码中产生类似的错误。但是,Clang 接受这样的函数 如果它们是成员函数 。这有效:
#include <iostream>
struct A {
virtual ~A() = 0;
};
struct B {
void f(void (*g)(A)) {
std::cout << "Works!" << std::endl;
}
};
int main() {
B().f(nullptr);
return 0;
}
不过,这似乎只是 Clang 中的一个错误。根据接受的答案中引用的标准部分中的语言,应该拒绝此代码。
[class.abstract]/3 说:
An abstract class shall not be used as a parameter type
设 A 为 C++ 中的抽象 class:
// legal
class A {
virtual void m() = 0;
}
定义抽象类型的变量当然是非法的class:
A a; // illegal
确实如此,clang
3.6.0 抱怨:
wat.cc:5:3: error: variable type 'A' is an abstract class
A a;
^
wat.cc:2:16: note: unimplemented pure virtual method 'm' in 'A'
virtual void m() = 0;
^
1 error generated.
同样,用抽象类型的参数定义函数也是非法的class:
void f(A a) {} // illegal
的确,clang
抱怨道:
wat.cc:5:10: error: parameter type 'A' is an abstract class
void f(A a) {}
^
wat.cc:2:16: note: unimplemented pure virtual method 'm' in 'A'
virtual void m() = 0;
^
1 error generated.
另一方面,定义一个类型为指向抽象值指针的变量当然是合法的 class:
A * a_ptr; // legal
即使 class 从未定义任何基础 class,类型 A *
至少有一个值,nullptr
,因此总是可以以类型正确的方式使用这样的变量,即使它可能不是很有用,除非 A
在某些时候得到一些具体的 subclasses:
a_ptr = nullptr; // legal
大概,这个推理适用于任何指针类型。
同样,定义一个接受参数的函数是合法的,该参数的类型是指向抽象值的指针class:
void f(A * a) {} // legal
同样,定义一个接受参数的函数是合法的,该参数的类型是指向函数的指针,该函数接受的参数类型是指向抽象值的指针class:
void f(void (* g)(A *)) {} // legal
这两个函数当然可以合法调用:
f(nullptr); // legal
据推测,函数参数的具体类型与类型的正确性无关,只要是指针类型即可。在任何一种情况下,对 f
的调用都应该是合法的。就类型论而言,格式良好的指针类型始终是合法的,并且 nullptr
始终存在于其中。根据这个推理,这个定义应该被推定为合法的:
void f(void (* g)(A)) {}
f
是一个接受参数的函数,该参数的类型是指向函数的指针,该函数接受的参数类型是抽象值 class A.
事实上,该参数的唯一可能值是 nullptr
,因为没有实际函数可以采用抽象类型的参数 class。
这符合 C++ 标准吗?
Clang 抱怨:
wat.cc:5:20: error: parameter type 'A' is an abstract class
void f(void (* g)(A)) {}
^
wat.cc:2:16: note: unimplemented pure virtual method 'm' in 'A'
virtual void m() = 0;
^
1 error generated.
GCC 没有。
更新:这个问题回答正确,但问题本身在声明 Clang 接受该功能时是错误的。 GCC 和 Clang 都会在这段代码中产生类似的错误。但是,Clang 接受这样的函数 如果它们是成员函数 。这有效:
#include <iostream>
struct A {
virtual ~A() = 0;
};
struct B {
void f(void (*g)(A)) {
std::cout << "Works!" << std::endl;
}
};
int main() {
B().f(nullptr);
return 0;
}
不过,这似乎只是 Clang 中的一个错误。根据接受的答案中引用的标准部分中的语言,应该拒绝此代码。
[class.abstract]/3 说:
An abstract class shall not be used as a parameter type