2017-06-06 91 views
0

我有一个C++代码,当前看起来像这样:有一个类层次结构来执行一些比较和使用它的列表类。基于某个模式对象在运行时确定要使用哪种比较操作。这里是结构:如何正确地用模板重写这个使用继承的C++代码

class A{ 
    bool doComparison(const string& s1, const string& s2) const=0; 
} 

class B: public A{ 
    bool doComparison(const string& s1, const string& s2) const { 
     ... 
    } 
} 

class C: public A{ 
    bool doComparison(const string& s1, const string& s2) const { 
     ... 
    } 
} 

template <class, S> 
public FancyList{ 
    shared_ptr<A> z_; 
    vector<S> v; 

    FancyList(shared_ptr<A> z) : z_(z); 

    void DoSmth(){ 
     .... 
     z_->doComparison(arg1, arg2); 
    } 

} 

typedef FancyList<string> FancyStringList; 

// Determine which comparison to use at runtime 
shared_ptr<A> c = nullptr; 
    switch(type): 
     case int: 
      c = make_shared<B>(); 
      break; 
     case double: 
      c = make_shared<B>(); 
      break; 
    FancyStringList l(c); 
    l.push_back("stuff"); 

C#曾经是我的主要语言,所以这段代码对我来说似乎没问题。但我被告知,这种方法的问题在于它使用虚函数,因此在方法调用中会有一些小的开销。什么是适当的C++ - 重新组织这段代码的方式,所以不需要拥有这个类的层次结构,也不需要使用虚函数?

+5

'do'是一个C++关键字。你不能用这个标识符来命名你的功能。 – StoryTeller

+1

'在运行时基于某个模式对象确定要使用哪种比较操作'。这意味着无论如何,你的程序必须花费一些CPU圈来选择比较方法,对吧?然后,我认为这种轻微的开销在这种情况下是可以接受的,它使您的代码更易于阅读和**扩展**。 –

+1

'switch'语句中的'type'是什么? –

回答

1

与你想要的相反,虚拟函数的开销是不可避免的,因为在运行时决定调用哪个实际函数。

如果决定总是在运行时进行,编译器不能将函数调用硬编码到生成的机器代码中。它必须是一个间接函数调用:使用指针指向函数,并在函数调用之前解引用指针。虚函数只是间接函数调用的一种方式。

模板是一种告诉编译器在编译期间生成代码的方式。所有模板可以做的是,以便在编译期间做出决定时不会引入开销。它无法帮助您删除必须在运行时完成的工作。


如果您仍然对使用模板感兴趣,可以考虑将比较器作为模板参数。

template <class T, class Comparator> 
class MyList 
{ 
    std::vector<T> vec; 
    Comparator comp; 

public: 
    void do_thing(const T& a, const T& b) 
    { 
     vec.push_back(a); 
     vec.push_back(b); 
     bool x = comp(vec[0], vec[1]); // for example 
     std::cout << x; 
    } 
}; 

在比较器类,重载函数调用操作

class Compare1 
{ 
public: 
    bool operator()(const std::string& lhs, const std::string& rhs) const 
    { 
     return lhs < rhs; 
    } 
}; 

class Compare2 
{ 
public: 
    bool operator()(const std::string& lhs, const std::string& rhs) const 
    { 
     return lhs.size() < rhs.size(); 
    } 
}; 

int main() 
{ 
    MyList<std::string, Compare1> myli1; 
    myli1.do_thing("a", "b"); 

    MyList<std::string, Compare2> myli2; 
    myli2.do_thing("c", "d"); 
} 

甚至可以隐藏比较器类后面的间接函数调用。但它并没有消除开销。

class A 
{ 
public: 
    virtual bool doComparison(const std::string& s1, const std::string& s2) const=0; 
    virtual ~A() = default; 
}; 

class PolymorphicComparator 
{ 
private: 
    std::shared_ptr<A> comp; 
public: 
    PolymorphicComp(std::shared_ptr<A> c) : comp(c) {} 

    bool operator()(const std::string& lhs, const std::string& rhs) const 
    { 
     return comp->doComparison(lhs, rhs); 
    } 
};