簡體   English   中英

盡管覆蓋但編譯錯誤

[英]Compile error despite override

抱歉,如果這是一個簡單的問題,那么對於c ++中的繼承, virtualoverride ,肯定有一些我不了解的地方。 在下面的示例中,我得到了一個與虛擬方法相關的編譯時錯誤,我專門重寫了該方法以避免子類發生此類錯誤。 難道我做錯了什么?

#include <array>
#include <deque>

template <class T, class C>
struct foo
{
    virtual const C& data() const =0;

    inline virtual T& operator[] ( unsigned n ) const
        { return const_cast<T&>( data()[n] ); }
};

/**
 * The implementation of foo::operator[] is useful for classes inheriting
 * with simple sequence containers like:
 *  foo<T,std::deque<T>>, foo<T,std::vector<T>>, ..
 *
 * But the following requires operator[] to be redefined:
 */

template <class T, unsigned N>
struct baz
    : public foo<T, std::deque<std::array<T,N>> > 
{
    typedef std::deque<std::array<T,N>> data_type;
    data_type m_data;

    inline const data_type& data() const 
        { return m_data; }
    inline virtual T& operator[] ( unsigned n ) const override
        { return const_cast<T&>( data()[n/N][n%N] ); }
};

int main()
{
    baz<double,3> b; // throws an error relative to foo::operator[] depsite override
}

編輯1錯誤:

clang++ -std=c++0x -Wall virtual_operator.cpp -o virtual_operator.o
virtual_operator.cpp:11:12: error: const_cast from 'const value_type' (aka 'const std::__1::array<double, 3>') to 'double &' is not allowed
                { return const_cast<T&>( data()[n] ); }
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~
virtual_operator.cpp:26:8: note: in instantiation of member function 'foo<double, std::__1::deque<std::__1::array<double, 3>, std::__1::allocator<std::__1::array<double, 3> > > >::operator[]'
      requested here
struct baz
       ^
1 error generated.

編輯2我認為這是問題的一部分; 如果由於foo::operator[]baz仍可調用而導致編譯失敗,那么如果我不將 foo::operator[]聲明為虛擬的(即隱藏而不是覆蓋),為什么它編譯正常?

問題是,盡管您只打算在baz實例上調用派生的operator[]函數,但是編譯器仍需要為基類生成代碼,因為該函數仍可在baz實例上調用。 在這種情況下,生成該代碼會導致類型錯誤,因為您正在嘗試將const std::array<double,3>轉換為double&

為了解決這個問題,您應該在層次結構的不同部分定義一個運算符,該運算符將對其所有子運算符起作用,如下所示(除去了非永久性的東西):

template <class T, class C>
struct foo
{
    inline virtual T& operator[] ( unsigned n ) const = 0;
};

template <class T>
struct bar
    : public foo<T,std::deque<T>>
{
    inline virtual T& operator[] ( unsigned n ) const override
        { return const_cast<T&>( data()[n] ); }
};

template <class T, unsigned N>
struct baz
    : public foo<T, std::deque<std::array<T,N>> >
{
    inline virtual T& operator[] ( unsigned n ) const override
        { return const_cast<T&>( data()[n/N][n%N] ); }
};

這樣,如果您要在以后添加任何其他版本,則可以從bar或baz派生,而無需為每個孩子定義運算符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM