C 中的模板和多態性
考慮以下類別結構:
<code class="cpp">class Interface { // ... }; class Foo : public Interface { // ... }; template <class T> class Container { // ... };</code>
其他類別的構造函數Bar 定義為:
<code class="cpp">Bar(const Container<Interface>& bar) { // ... }</code>
但是,當嘗試以下列方式呼叫建構函式時:
<code class="cpp">Container<Foo> container(); Bar *temp = new Bar(container);</code>
我們遇到「無符合函數」錯誤。
模板中的多態性
模板中的多態性或模板協方差的概念意味著如果類別B 繼承自類A,則T同樣繼承自T A 。然而,在 C 或 Java 或 C# 等其他語言中,情況並非如此。
缺乏模板協方差的原因
缺乏模板協方差的理由是需要維護類型安全。考慮以下範例:
<code class="cpp">// Class hierarchy class Fruit {...}; class Apple : public Fruit {...}; class Orange : public Fruit {...}; // Template instantiation using std::vector int main() { std::vector<Apple> apple_vec; apple_vec.push_back(Apple()); // Valid // With covariance, the following would be allowed std::vector<Fruit>& fruit_vec = apple_vec; // Adding an Orange to the vector fruit_vec.push_back(Orange()); // Incorrect addition of an orange to an apple vector }</code>
這表示如果範本是協變的,則可能會出現不安全行為。因此,T A 是和T B 。無論 A 和 B 之間的關係如何,都被視為完全不同的類型。
解決問題
在Java 和C# 中解決問題的一種方法是使用有界通配符和約束分別為:
<code class="java">Bar(Container<? extends Interface) {...}
<code class="csharp">Bar<T>(Container<T> container) where T : Interface {...}</code>
在C 語言中,Boost Concept Check 函式庫可以提供類似的功能。然而,對於遇到的特定問題,使用簡單的靜態斷言可能是更實用的解決方案:
<code class="cpp">static_assert(std::is_base_of<Interface, Foo>::value, "Container must hold objects of type Interface or its derived classes.");</code>
以上是為什麼 C 不支援模板協變,以及在使用多型模板時如何解決由此產生的型別安全問題?的詳細內容。更多資訊請關注PHP中文網其他相關文章!