在 C++ 中使用匿名 Class 实现接口
Implement Interface with Anonymous Class in C++
在 java 中,我们可以像这样使用匿名 class 实现 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>
)
这是怎么回事?还有其他方法吗?
谢谢!
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;
}
what's wrong here?
要使多态性起作用,您需要通过引用(或指针,如果您愿意)传递基 class:
bool testIf(T t, Predicate<T> & predicate)
^
修复后,代码对我有用,尽管它闻起来 Java 对我来说太过分了。
are there other ways to do it?
在 C++11 或更高版本中,lambda 在性能和代码噪声方面都更高效。它消除了定义和继承基础 class 以及调用虚函数的需要。
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 之前,您可以用函数对象做同样的事情。它稍微冗长一些,但仍然提供比继承方法更短、更高效的代码。)
为了使这个(多态性)起作用,您必须通过指针或通过引用 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;
}
我通常更喜欢使用指针,因为在使用引用时,我往往会忽略多态性的可能性。另一方面,它有缺点,你必须检查 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;
}
在 java 中,我们可以像这样使用匿名 class 实现 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>
)
这是怎么回事?还有其他方法吗?
谢谢!
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;
}
what's wrong here?
要使多态性起作用,您需要通过引用(或指针,如果您愿意)传递基 class:
bool testIf(T t, Predicate<T> & predicate)
^
修复后,代码对我有用,尽管它闻起来 Java 对我来说太过分了。
are there other ways to do it?
在 C++11 或更高版本中,lambda 在性能和代码噪声方面都更高效。它消除了定义和继承基础 class 以及调用虚函数的需要。
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 之前,您可以用函数对象做同样的事情。它稍微冗长一些,但仍然提供比继承方法更短、更高效的代码。)
为了使这个(多态性)起作用,您必须通过指针或通过引用 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;
}
我通常更喜欢使用指针,因为在使用引用时,我往往会忽略多态性的可能性。另一方面,它有缺点,你必须检查 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;
}