2017-01-21 1 views
2

はのは、このコードを考えてみましょう:明示的なスコープ解決なしに親クラスの親のメソッドにアクセスできないのはなぜですか?

struct message 
{ 
    uint8_t* data; 
    size_t length; 
}; 

class device_base 
{ 
    // ... 
public: 
    virtual ssize_t exec(uint8_t cmd, const uint8_t* data = nullptr, size_t length = 0); 
    inline ssize_t exec(uint8_t cmd, const message& msg) 
    { 
    return exec(cmd, msg.data, msg.length); 
    } 
    // ... 
}; 

class device : public device_base 
{ 
    // The exec method do not overloaded or overridden here. 
}; 

class device_uart : public device 
{ 
    // ... 
public: 
    ssize_t exec(uint8_t cmd, const uint8_t* data = nullptr, size_t length = 0); 
    void some_method(const message&); 
    // ... 
}; 

// ... 

void device_uart::some_method(const message& msg) 
{ 
    // exec(SOME_COMMAND, msg); // The inline method device_base::exec is invisible here by some reason. 
    device::exec(SOME_COMMAND, msg); // OK. 
    device_base::exec(SOME_COMMAND, msg); // OK too. 
    exec(SOME_COMMAND, msg.data, msg.length); // OK, of course. 
} 

インライン非仮想メソッドexecdevice_uartクラスでは見られないのはなぜ?

+1

私はそれの上に注いだので、それはしばらくの間をされているが、私はかなり確信している[**この質問**](https://stackoverflow.com/questions/1628768/why-does-an-overridden-クラスの派生クラス - 非 - 他のオーバーロード - )は、あなたが求めているように見えるものを正確にカバーしています。 – WhozCraig

答えて

3

インライン非仮想メソッドexecdevice_uartクラスに表示されないのはなぜですか?

これは「名前の隠れ」の一種です。 device_uartのメンバ関数ではという名前のexecという名前のメソッドがあるため、device_base::execが非表示になっています。関数は異なるスコープでオーバーロードすることはできません。

unqualified name lookupの規則によれば、それはその時点で検索が停止し ないさらなるスコープは、任意の種類の 少なくとも一つの宣言で見つかるまで、以下に説明するように

ネームルックアップがスコープを調べ調べた名前execを意味

device_uartの範囲で発見され、その後、ルックアップ停止に名前を付け、基底クラス内の名前は全くオーバーロードの解決のために考慮されることはありません。

この問題を解決するには、スコープ解決演算子::を使用して、これを図のようにqualified name lookupにできます。または usingを使用して名前を同じスコープに導入すると、オーバーロードの解像度が期待どおりに反映されます。例えば

class device_uart : public device 
{ 
    // ... 
    using device_base::exec; // introduce the names from base class into the same scope 
public: 
    // ... 
}; 
関連する問題