用C++实现匿名类接口
Implement Interface with Anonymous Class in C++
在java中,我们可以用匿名类实现interface
,如下所示:
import java.util.function.Predicate;
public class Test {
public static void main(String[] args) {
System.out.println(testIf("", new Predicate<String>() {
@Override
public boolean test(String s) {
return s.isEmpty();
}
}));
}
public static <T> boolean testIf(T t, Predicate<T> predicate) {
return predicate.test(t);
}
}
自Java 8:
System.out.println(testIf("", String::isEmpty));
我们如何在c++中做到这一点?我写了以下代码,但我得到了编译错误:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
template <class T>
class Predicate
{
public:
virtual bool test(T) = 0;
};
template <class T>
bool testIf(T t, Predicate<T> predicate)
{
return predicate.test(t);
}
int main()
{
class : public Predicate <string> {
public:
virtual bool test(string s)
{
return s.length() == 0;
}
} p;
string s = "";
cout << testIf(s, p);
cin.get();
return 0;
}
错误:没有函数模板"testIf"的实例与参数列表匹配参数类型为:(std::string
,class <unnamed>
)
这里怎么了?有其他方法吗?
谢谢!
这里怎么了?
为了使多态性发挥作用,您需要通过引用(或者指针,如果您愿意的话)传递基类:
bool testIf(T t, Predicate<T> & predicate)
^
修复后,代码对我来说是有效的,尽管它闻起来太像Java了。
有其他方法吗?
在C++11或更高版本中,lambda在性能和代码噪声方面都会更高效。它消除了定义基类和从基类继承以及调用虚拟函数的需要。
template <class T, class Predicate>
bool testIf(T t, Predicate predicate)
{
return predicate(t);
}
testIf(s, [](string const & s){return s.length() == 0;});
(在C++11之前,你可以对函数对象做同样的事情。它稍微更详细,但仍然比继承方法提供更短、更高效的代码。)
C++只支持引用和指针类型上的多态性。将您的方法更改为
template <class T>
bool testIf(T t, Predicate<T> & predicate)
{
return predicate.test(t);
}
那么您也可以将Predicate
的子类传递给这个函数。
您可以为函数使用一个指针:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
template <class T>
class Predicate
{
public:
bool (*test)(T);
};
template <class T>
bool testIf(T t, Predicate<T> predicate)
{
return predicate.test(t);
}
bool one_test(string e)
{
return e.length() == 0;
}
int main()
{
Predicate<string> p;
p.test = one_test;
string s = "";
cout << testIf(s, p);
cin.get();
return 0;
}
为了使这种(多态性)发挥作用,您必须通过指针或引用将谓词传递给testIF:
template <class T>
bool testIf(T t, Predicate<T>* predicate)
{
if (predicate == nullptr) return true;
return predicate->test(t);
}
int main()
{
class : public Predicate <string> {
public:
virtual bool test(string s)
{
return s.length() == 0;
}
} p;
string s = "";
cout << testIf(s, &p);
cin.get();
return 0;
}
我通常更喜欢使用指针,因为当使用引用时,我倾向于忽略多态性的可能性。另一方面,它有disatvantage,你必须检查nullptr,语法也不像以前那么好了。
实现这一点的一种更常见的方法是使用lambdas,例如:
template <class T,class Pred>
bool testIf2(T t, Pred predicate)
{
return predicate(t);
}
int main()
{
auto pred = [](const string& s){return s.length() == 0; };
string s = "";
cout << testIf2(s, pred );
cin.get();
return 0;
}
相关文章:
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- Visual C++GC接口如何启用它以及要包含哪个库
- Windows.h与GLFW.h的接口
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 提供与TMP和SFINAE的通用接口
- 为重写std::exception的库生成swig接口时出错
- 内联如何影响模块接口中的成员函数
- COM 接口 c# 封送数组数组
- 如何在 SCIP C++ 接口中获取 MILP 约束矩阵中的系数值
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 如何绑定 C++ gRPC 客户端的网络接口
- 模板化接口 - 创建一个泛型模板类以返回任何容器
- 如何从实现接口的模板化类实例访问结构
- 带有进度表的 curl 多接口程序
- 设计帮助 - 为不同类型的消息处理通用接口的设计模式
- 我可以在具有一个标头和一个接口的 cpp 文件中有多个嵌入吗?
- 类接口,可以创建N个方法
- 类具有相同的接口,但参数的类型不同
- 如何与 Cheerp/js 中的 extern 变量接口?
- 如何使用现代 CMake 安装捆绑的接口依赖项?