簡體   English   中英

C++ 中的集合(異構類型的數組)

[英]Sets (arrays of heterogeneous types) in C++

我想用 C++ 模擬 python 集。 根據faq ,一種慣用的方法是使用std::vector將指針(如果智能指針更好)存儲到句柄類,然后由我們想要存儲在模擬中的特定類型重載放。

這是我的嘗試:

// experimenting with vectors of heterogeneous elements (like sets in python)
#include <iostream>
#include <memory>
#include <string>
#include <vector>


// Handle can wrap an int, a double, or a string.
class Handle {
public:
  Handle();
  virtual int val();
  virtual double val();
  virtual std::string val();
};


class Int : public Handle {
public:
  Int(const int n) : value(n) {};
  int val() override { return value; };
private:
  int value;
};


class Double : public Handle {
public:
  Double(const double n) : value(n) {};
  double val() override { return value; };
private:
  double value;
};


class String : public Handle {
public:
  String(const std::string& n) : value(n) {};
  std::string val() override { return value; };
private:
  std::string value;
};


int main() {
  // v simulates a set with 12 elements of types int, double, or string.
  std::vector<std::shared_ptr<Handle>> v(12);

  for (int i = 0; i < v.size(); i += 3) {
    v[i] = std::shared_ptr<Int>(new Int(i));
    v[i + 1] = std::shared_ptr<Double>(new Double(i + 1.));
    v[i + 2] = std::shared_ptr<String>(new String(std::to_string(i + 2)));
  }

  for (auto& it : v) {
    std::cout << it->val() << std::endl;
  }
}

這種方法比將v聲明為std::vector<Handle*>更可取,因為使用智能指針可以讓我忘記手動刪除指針,同時實現運行時多態性。

但是上面的代碼不能編譯,因為我們不允許只在返回類型上重載函數(在這種情況下是val() )。

有沒有辦法修復我的代碼,以便我可以模擬具有不同類型的集合? 有沒有更好的,慣用的方法來做到這一點?

編輯

這是我在 n 之后更改代碼的方式。 '代詞' m. 的回答。 代碼似乎有效,我很高興將它作為使用繼承和智能指針的練習(即使它不是手頭特定問題的最佳解決方案,請參閱 Maxim Egorushkin 的答案以獲得更好的方法)。

// experimenting with vectors of heterogeneous elements (like sets in python)
#include <iostream>
#include <memory>
#include <string>
#include <vector>


// Handle can wrap an int, a double, or a string.
class Handle {
public:
  Handle() {};
  virtual void print(std::ostream&) = 0;
};


class Int : public Handle {
public:
  Int(const int n) : value(n) {};
  void print(std::ostream& s) override { s << value << std::endl; };
private:
  int value;
};


class Double : public Handle {
public:
  Double(const double n) : value(n) {};
  void print(std::ostream& s) override { s << value << std::endl; };
private:
  double value;
};


class String : public Handle {
public:
  String(const std::string& n) : value(n) {};
  void print(std::ostream& s) override { s << value << std::endl; };
private:
  std::string value;
};


int main() {
  std::vector<std::shared_ptr<Handle>> v(12);

  for (size_t i = 0; i < v.size(); i += 3) {
    v[i] = std::shared_ptr<Int>(new Int(i));
    v[i + 1] = std::shared_ptr<Double>(new Double(i + 1.));
    v[i + 2] = std::shared_ptr<String>(new String(std::to_string(i + 2)));
  }

  for (const auto& it : v) {
    it->print(std::cout);
  }
}

我想用 C++ 模擬 python 集。 根據常見問題解答,一種慣用的方法是使用存儲指針的std::vector ......

C++ 中的std::setstd::set (通常是紅黑樹)和std::unordered_set (哈希表)。 std::vector是一個可調整大小的數組。

如果您知道要存儲在集合中的所有類型,請使用std::variant作為值,而不是指針。

例如:

#include <unordered_set>
#include <variant>
#include <string>

int main() {
    using Value = std::variant<int, double, std::string>;
    using ValueSet = std::unordered_set<Value>;

    ValueSet s;
    s.insert(1);       // int
    s.insert(3.14);    // double
    s.insert("hello"); // string

    for(auto const& value : s)
        visit([](auto&& v) { std::cout << v << '\n'; }, value);
}

C++ 是一種靜態類型語言。 每個表達式都有一個靜態確定的類型。 這意味着您、tge 編譯器和其他所有人都可以僅從程序文本中確定類型,而無需嘗試執行任何代碼。

(由 tge 表達式表示的對象也可能具有動態類型,在運行時確定,但這不是我們所關心的)。 一種

我們來看看這個表達。

it->val()

它的類型是什么?

唯一可能的答案是std::string 事實上, it的類型是std::shared_ptr<Handle> ,並且Handle::val被指定為返回std::string Handle具有派生類型這一事實Handle 無論指向對象的動態類型是什么, it->val()靜態類型是std::string ,如果某事物具有std::string靜態類型,則它不能具有動態類型,例如double 這就是您不能以這種方式覆蓋val的原因。

那么如果我們想根據對象的動態類型打印不同的東西該怎么辦呢?

標准的 OOP 解決方案是有一個打印的方法,與返回要打印的東西的方法相反。 在 C++ 術語中,這將是一個虛函數,例如

virtual void print() = 0;

在每個派生類中重寫。

當然,現實生活並沒有那么簡單。 如果我們需要打印到任意流怎么辦? 我們需要將流作為參數傳遞給print 也許我們需要傳遞更多的東西。 也許我們想指定打印字段的寬度、精度或其他任何內容。 如果我們除了打印之外還想做一堆其他的事情怎么辦? 對於我們想做的每件事,我們是否需要一個單獨的方法? OOP 研究這些和更多問題的答案,但我無法在一個 SO 帖子中回答它們:(

暫無
暫無

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

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