0

我試圖推廣我的課使用基於策略的設計,似乎gcc沒有看到在基類中實現的純虛函數的實現。這裏有一個例子:GCC沒有看到通過多繼承實現

#include <iostream> 

template <typename ReturnValue, template <typename> class... AccessPolicies> 
struct testInterface : public AccessPolicies<ReturnValue>::interface... 
{ 

}; 

template <typename DataClass, typename ReturnValue, template <typename> class... AccessPolicies> 
struct testImplementation : public DataClass, 
           public testInterface< ReturnValue, AccessPolicies... >, 
           public AccessPolicies<ReturnValue>::template implementation<DataClass>... 
{ 

}; 

template < typename ReturnValue > 
struct GetByIndex; 

template <> 
struct GetByIndex<std::string> 
{ 
    class interface 
    { 
    public: 
     virtual std::string operator[](size_t) = 0; 
    protected: 
     virtual ~interface() = default; 
    }; 

    template <class DataClass> 
    class implementation 
    { 
    public: 
     virtual std::string operator[](size_t) 
     { 
      return "test by index"; 
     } 
    protected: 
     virtual ~implementation() = default; 
    }; 
}; 

template < typename ReturnValue > 
struct GetByName; 

template <> 
struct GetByName<std::string> 
{ 
    class interface 
    { 
    public: 
     virtual std::string operator[](std::string) = 0; 
    protected: 
     virtual ~interface() = default; 
    }; 

    template <class DataClass> 
    class implementation 
    { 
    public: 
     virtual std::string operator[](std::string) 
     { 
      return "test by string"; 
     } 
    protected: 
     virtual ~implementation() = default; 
    }; 
}; 

struct data 
{ 

}; 

int main() 
{ 
    testImplementation< data, std::string, GetByIndex, GetByName> test; 
    testInterface< std::string, GetByIndex, GetByName >& Test = test; 

    std::cout << Test[5] << std::endl; 

    return 0; 
} 

錯誤我越來越有:

..\nienazwany\main.cpp: In function 'int main()': 
..\nienazwany\main.cpp:78:67: error: cannot declare variable 'test' to be of abstract type 'testImplementation<data, std::basic_string<char>, GetByIndex, GetByName>' 
    testImplementation< data, std::string, GetByIndex, GetByName> test; 
                   ^
..\nienazwany\main.cpp:10:8: note: because the following virtual functions are pure within 'testImplementation<data, std::basic_string<char>, GetByIndex, GetByName>': 
struct testImplementation : public DataClass, 
     ^
..\nienazwany\main.cpp:53:29: note:  virtual std::string GetByName<std::basic_string<char> >::interface::operator[](std::string) 
     virtual std::string operator[](std::string) = 0; 
          ^
..\nienazwany\main.cpp:26:29: note:  virtual std::string GetByIndex<std::basic_string<char> >::interface::operator[](size_t) 
     virtual std::string operator[](size_t) = 0; 
          ^
..\nienazwany\main.cpp:81:24: error: request for member 'operator[]' is ambiguous 
    std::cout << Test[5] << std::endl; 
         ^
..\nienazwany\main.cpp:53:29: note: candidates are: virtual std::string GetByName<std::basic_string<char> >::interface::operator[](std::string) 
     virtual std::string operator[](std::string) = 0; 
          ^
..\nienazwany\main.cpp:26:29: note:     virtual std::string GetByIndex<std::basic_string<char> >::interface::operator[](size_t) 
     virtual std::string operator[](size_t) = 0; 

有兩個問題的,我不完全得到:

  1. 編譯器似乎不考慮AccessPolicy<ReturnType>::implementation<DataClass>...即使函數簽名完全相同,也要執行AccessPolicy<ReturnType>::interface...
  2. 編譯器無法解析哪個運算符[]我打電話,即使它們都有不同的參數,我清楚地調用size_t(數字不能隱式轉換爲字符串)。

任何想法爲什麼會發生這種情況?

我的猜測是,即使我直接從「接口」和「實現」繼承,成員函數以某種方式結束於不同的命名空間。如果這是正確的,我該如何解決這個問題?


編輯:加入剝離模板的上述例子中,按請求

#include <iostream> 

class GetByIndexInterface 
{ 
public: 
    virtual std::string operator[](size_t) = 0; 
protected: 
    virtual ~GetByIndexInterface() = default; 
}; 

class GetByIndexImplementation 
{ 
public: 
    virtual std::string operator[](size_t) 
    { 
     return "test by index"; 
    } 
protected: 
    virtual ~GetByIndexImplementation() = default; 
}; 


class GetByNameInterface 
{ 
public: 
    virtual std::string operator[](std::string) = 0; 
protected: 
    virtual ~GetByNameInterface() = default; 
}; 

class GetByNameImplementation 
{ 
public: 
    virtual std::string operator[](std::string) 
    { 
     return "test by string"; 
    } 
protected: 
    virtual ~GetByNameImplementation() = default; 
}; 

struct data 
{ 

}; 

struct testInterface : public GetByIndexInterface, 
         public GetByNameInterface 
{ 

}; 

struct testImplementation : public data, 
           public testInterface, 
           public GetByIndexImplementation, 
           public GetByNameImplementation 
{ 

}; 

int main() 
{ 
    testImplementation test; 
    testInterface& Test = test; 

    std::cout << Test[5] << std::endl; 

    return 0; 
} 
+0

你可能會構建一個更簡單的測試案例更容易閱讀嗎?也許現在消除所有複雜的模板東西? –

+0

添加了沒有所有模板的等效測試用例。 – tsuki

+0

謝謝,這是更容易遵循! –

回答

1

struct testImplementationstruct testInterface本身繼承繼承從struct GetByNameInterface其限定virtual std::string operator[](std::string) = 0;

testInterfacetestImplementation都沒有定義這個虛擬的覆蓋,所以testImplementation是一個抽象的結構。

事實上,你從另一個類與前一個沒有關係,但定義相同的operator不會幫助你。你必須在具體實現和抽象接口之間的層次結構中實現你的方法,而不是在一個側面類。

+0

@tsuki這對繼承無濟於事。有一個爲你繼承的每個類定義的虛擬函數表,編譯器只需要在你的類和它的祖先中定義的元素直接定義虛擬元素來填充它。其他繼承類不在這個遊戲中玩。 – Johan

+0

一旦我注意到您的編輯添加了最後一段,我就刪除了我的帖子。抱歉。有關如何解決此問題的任何提示? – tsuki

+0

@tsuki你真的需要一個具有虛擬方法的類層次嗎? – Johan

0

爲了做到這一點,implementation類必須繼承自你的interface類,這種方式的實現將被接受,但如前所述,繼承自一個抽象函數實現的無關類,並不意味着實現的函數應該考慮作爲抽象函數的實現

+0

如果我得到這個權利 - 我試圖讓'implementation'從'interface'繼承,但它似乎不起作用。 – tsuki