簡體   English   中英

operator== 標記為“覆蓋”,但不覆蓋

[英]operator== marked 'override', but does not override

我在覆蓋基類 operator== 時遇到問題。 這是代碼。

#include <iostream>
#include <vector>

using namespace std;

template <typename T>
class IClient {
  virtual const std::vector<T>& getID() = 0;
  virtual bool isEqual(const std::vector<T>& anotherID) = 0;
  virtual bool operator==(const IClient& anotherClient) = 0;
};

class SeviceClient : public IClient<int8_t> {
  const std::vector<int8_t> ID;

 public:
  SeviceClient(const std::vector<int8_t>& ID) : ID(std::move(ID)) {}
  SeviceClient(const std::vector<int8_t>&& ID) : ID(std::move(ID)) {}

  const std::vector<int8_t>& getID() override {
      return ID;
  }
  bool isEqual(const std::vector<int8_t>& anotherID) override {
      return true;
  }
  bool operator==(const SeviceClient& anotherClient) override {
      return true;
  }
};

它抱怨說

 error: 'bool SeviceClient::operator==(const SeviceClient&)' marked 'override', but does not override

當我將函數轉換為時,編譯器看起來很高興

bool operator==(const IClient<int8_t>& anotherClient) override {}

這是問題的解決方案還是我在這里遺漏了什么?

謝謝

ServiceClient 和 IClient 是不同的類型。 因此, bool SeviceClient::operator==(const SeviceClient&) 沒有基本聲明。

您必須了解 C++ 有可能重載函數。 因此,要識別假設被調用的函數,不僅函數名必須匹配,而且參數的類型也必須匹配。 當然有隱式轉換,它可以調整參數以匹配函數參數類型,但請注意,如果有多個具有相同名稱的函數,那么隱式轉換可能會導致歧義。

如果您正在使用多態,那么您必須記住子類應該是可用的,因為它只是父類。 持有指向基類的指針的人不應該注意到它實際上是一個子類。

所以當你覆蓋虛函數類型的參數時必須非常精確,所以一切都是明確的。

我懷疑您需要靜態多態性和 CRTP 而不是動態多態性。 所以像這樣:

template <typename Child, typename T>
class IClient {
  const std::vector<T>& getID() {
      return asChild()->getID();
  }

  bool isEqual(const std::vector<T>& anotherID) {
      return asChild()->isEqual(anotherID);
  }

  bool operator==(const Child& anotherClient) {
      return asChild()->isEqual(anotherClient);
  }

private:
  Child* asChild() {
      return static_cast<Child*>(this);
  }
  const Child* asChild() const {
      return static_cast<const Child*>(this);
  }

};

class SeviceClient : public IClient<SeviceClient, int8_t> {
  const std::vector<int8_t> ID;

public:
  SeviceClient(const std::vector<int8_t>& ID) : ID(std::move(ID)) {}
  SeviceClient(const std::vector<int8_t>&& ID) : ID(std::move(ID)) {}

  const std::vector<int8_t>& getID() {
      return ID;
  }
  bool isEqual(const std::vector<int8_t>& anotherID) {
      return true;
  }
  bool operator==(const SeviceClient& anotherClient) {
      return true;
  }
};

這個問題有兩個方面。 一,這種設計違反了 C++ 的哪些規則? 第二,為什么 C++ 有這樣的規則?

第一個很容易。 您可以通過具有完全相同參數列表的函數來覆蓋函數。 由於(const IClient& anotherClient)是不完全一樣的(const SeviceClient& anotherClient)沒有重寫發生。 案件結案。

第二個涉及更多。 為了理解它,讓我們使用一個更熟悉的類層次結構。 class Animal ,有class Dog : public Animalclass Cat : public Animal

什么bool Animal::operator==(const Animal&)告訴我們什么? 它告訴我們可以將一種動物與另一種動物進行比較。 特別是,我們可以將狗與狗、貓與貓、狗與貓、老鼠與蝙蝠、魚與蚊子、土豚與霸王龍進行比較。 這是class Animal讓你成為我們的承諾 如果我們有兩個Animal對象,我們可以比較它們。

現在,重寫此運算符的函數應該履行承諾。 bool Dog::operator==(const Dog&)會這樣做嗎? 不,它實現了一個更狹隘的承諾:可以將這個Animal (恰好是一個Dog )與一個Dog進行比較。 實現這個狹隘的應許是否合法? 絕對地。 假裝這個功能也實現了廣泛的承諾,即能夠比較任何兩只動物,是否合法? 絕對不。 所以我們可以聲明這個函數,但不能聲稱它覆蓋了Animal相等運算符。

如果有一條規則允許我們聲明,會發生什么?

Dog d;
Cat c;
Animal& da = d;
Animal& ca = c;
std::cout << (da == ca);

這個程序片段必須編譯,因為每一行都是有效的(根據我們的幻想規則),但它應該做什么 沒有代碼可以將狗與貓進行比較!

有些語言說“好吧,沒什么大不了的,我們只會拋出一個運行時錯誤”。 C++ 不這樣做。 如果你想讓上面的代碼拋出運行時錯誤,你應該自己編寫拋出運行時錯誤的代碼。 這意味着用bool Dog::operator==(const Animal&)bool Cat::operator==(const Animal&)覆蓋bool Animal::operator==(const Animal&) bool Cat::operator==(const Animal&) ,並檢查那里的錯誤條件。

不過,這可能不是一個好主意。 平等通常對類層次結構沒有意義。 完全省略比較或使其非虛擬並僅在子類中定義通常是一個更好的主意。

暫無
暫無

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

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