C 接口无虚拟函数
C++ interface without virtual functions
我想知道我们如何在不使用虚拟函数的情况下声明C 中的接口。互联网搜索后,我整理了此解决方案:
#include <type_traits>
using namespace std;
// Definition of a type trait to check if a class defines a member function "bool foo(bool)"
template<typename T, typename = void>
struct has_foo : false_type { };
template<typename T>
struct has_foo<T, typename enable_if<is_same<bool, decltype(std::declval<T>().foo(bool()))>::value, void>::type> : true_type { };
// Definition of a type trait to check if a class defines a member function "void bar()"
template<typename T, typename = void>
struct has_bar : false_type { };
template<typename T>
struct has_bar<T, typename enable_if<is_same<void, decltype(std::declval<T>().bar())>::value, void>::type> : true_type { };
// Class defining the interface
template <typename T>
class Interface{
public:
Interface(){
static_assert(has_foo<T>::value == true, "member function foo not implemented");
static_assert(has_bar<T>::value == true, "member function bar not implemented");
}
};
// Interface implementation
class Implementation:Interface<Implementation>{
public:
// If the following member functions are not declared a compilation error is returned by the compiler
bool foo(bool in){return !in;}
void bar(){}
};
int main(){}
我打算在一个仅使用静态多态性的项目中使用此设计策略。我将在项目中使用的C 标准是C 11。
您认为这种方法的利弊是什么?
我提出的代码可以进行哪些改进?
编辑1:我只是意识到不需要从接口继承。此代码也可以使用:
class Implementation{
Interface<Implementation> unused;
public:
bool foo(bool in){return !in;}
void bar(){}
};
编辑2-3:static_assert解决方案(有或没有CRTP(与标准CRTP之间的一个主要区别在于,CRTP不能保证派生的类实现所有接口成员。例如,正确编译以下代码:
#include <type_traits>
using namespace std;
template< typename T>
class Interface{
public:
bool foo(bool in){
return static_cast<T*>(this)->foo(in);
}
void bar(){
static_cast<T*>(this)->bar();
}
};
class Implementation: public Interface<Implementation>{
public:
// bool foo(bool in){return !in;}
// void bar(){}
};
int main(){}
仅当功能 foo 或 bar 时,编译器才会返回有关丢失的成员函数的错误。
我看到的方式,static_assert解决方案感觉更像是接口声明,而不是单独使用CRTP。
实现静态多态性的一种常见方法是使用CRTP。
使用此模式,您定义了一个模板的接口类,其方法将其转发到模板:
// Interface
template <typename T>
struct base {
void foo(int arg) {
static_cast<T*>(this)->do_foo(arg);
}
};
您从基类实现继承并实现方法:
// Implementation
struct derived : base<derived> {
void do_foo(int arg) {
std::cout << arg << 'n'
}
};
这种模式的优势是它看起来"感觉"很像常规的运行时多态性,并且错误消息通常很理智。因为编译器可以看到所有代码,所以所有内容都可以夹住,因此没有开销。
您似乎要实现概念(Lite(。您可能需要在尝试实施之前阅读文章。
缺乏编译器支持,您可以部分实现此想法。您的static_assert
想法是表达接口要求的已知方法。
考虑链接中的Sortable
示例。您可以创建类模板Sortable
,使用static_assert
来主张所有对模板参数的思考。您向用户解释他们需要实现某种CET的方法,并实施该设置,他们需要以一种或另一种方式使用Sortable<TheirClass>
。
为了在函数声明中表达。您的功能需要Sortable
的想法,您必须诉诸类似的东西:
template <typename Container>
auto doSomethingWithSortable (Container&) -> std::enable_if<Implements<Container, Sortable>>::type;
- C++无法定义虚拟函数 OUTER 类和头文件
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 当覆盖存在时调用基本虚拟"binded to object"函数
- 如何在C++中伪造虚拟可变参数函数模板?
- 类型擦除的std::function与虚拟函数调用的开销
- 重写虚拟函数和继承
- 是否可以使用函数指针调用虚拟析构函数?
- 在没有动态内存的世界中,我是否需要虚拟析构函数?
- 虚拟继承基构造函数消除
- "虚拟""覆盖"析构函数
- 类中的虚拟布尔函数参数不起作用
- 用纯虚拟函数兜圈子
- 将C++子类成员函数(虚拟实现)传递给 C 类型函数指针
- 尝试在 QLabel 上绘画失败(无法在没有对象的情况下调用成员函数"虚拟无效 QLabel::p aintEvent(QPaintEvent*)")
- 声明析构函数虚拟就足够了吗?
- 视觉 C++当我们在基类中使函数成为纯虚拟时,那么在子类中再次使相同的函数虚拟的必要性是什么
- 重载函数(虚拟/非虚拟)