2015-02-24 44 views
6

在Java中,我们可以实现匿名类的interface这样实现接口:与++匿名类用C

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::stringclass <unnamed>

这里有什么问题?还有其他方法可以做到吗?

谢谢!

+2

你可以看看http://stackoverflow.com/questions/991062/passing-unnamed-classes-through-functions – Prashant 2015-02-24 10:41:01

回答

9

有什么不对吗?

对于多态性的工作,你需要按引用传递基类(或指针,如果你喜欢):

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之前,你可以做同样的事情用一个函数对象,这是稍微详细,但还是给了短,比继承方法更高效的代码。)

3

C++仅支持引用和指针类型的多态性。将您的方法更改为

template <class T> 
bool testIf(T t, Predicate<T> & predicate) 
{ 
    return predicate.test(t); 
} 

然后您还可以将Predicate的子类传递给此函数。

+0

这是真的太多,我没看出来:) – amchacon 2015-02-24 10:46:44

3

你可以用一个指针函数:

#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; 
} 
3

在为了使这一(多态性)工作,您必须通过指针或引用传递谓词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; 
} 

我通常喜欢使用指针,因为我往往忽略多态性的posibility,当引用用过的。另一方面,它有缺点,你必须检查nullptr,并且语法不像以前那么好。

更常见的实现方法是使用lambda表达式。:

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; 
}