2017-06-06 39 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); 
    } 
};