以下是我設計的一些架構。我有一個類 X,它有一個變數成員 Y,它是指向類 A 的指標(或參考,我還沒有決定)。類 A 是一個抽象類。X 的用戶可以從 A(例如 B:A)創建他自己的派生類并將其傳遞給 X(可能在建構式中),X 會以某種方式將其存盤在 Y 中。
為了使這個作業,用戶應該動態分配一個 B:A 型別的物件并將它傳遞給 X。但是,你能想出一種更簡單的方法,對于用戶來說,這樣做而不必呼叫new嗎?理想情況下,我希望用戶簡單地創建一個 B:A 型別的物件并傳遞它。然后,X 的建構式會以某種方式使用它定義 Y(可能會創建 B:A 的副本)。問題是 X 不知道傳遞了哪個派生型別以及它的大小。
我想創建一個建構式,用戶可以將派生自 A 的任何型別作為引數傳遞給該建構式,并將其轉換為成員變數。它應該允許用戶創建自己的型別以利用多型性。
class A {...}; // Abstract class (has pure virtual members)
class B : public A {...}; // Class defined by the user
class X
{
public:
X(A ¶m) { /* abc is defined */ }
A* abc;
}
我有一些想法:它可以作業在 A 處多載的純虛擬副本賦值運算子嗎?并且在 B:A 有一個成員指定 B:A 的大小?但是我仍然不知道如何使它作業。
如何解決?有沒有更好的方法?提前致謝。
uj5u.com熱心網友回復:
為了使這項作業,用戶應該動態分配一個型別的物件
B:A并將其傳遞給X. 但是,您能想出一種更簡單的方法,讓用戶無需呼叫即可執行此操作new嗎?
多型性不依賴于new被使用。它只需要一個指向多型物件的指標/參考。如果需要,呼叫者可以靜態創建其派生物件。只要X物件比參考它的物件壽命長。
然后, 的建構式
X會以某種方式定義Y使用它
這是不可能的。該Y成員必須在編譯時進行靜態型別化,即作為A*指標或A&參考。除非X被撰寫為模板類,以便用戶可以指定傳入的實際派生型別。
也許創建一個副本
B:A
這是可能的,但前提X是模板化,否則A必須宣告一個clone()所有派生類都覆寫的虛擬方法以復制它們自己。
問題是
X不知道傳遞了哪個派生型別以及它的大小。
多型性不需要知道這些資訊。
uj5u.com熱心網友回復:
您可以簡單地要求該類實作復制操作(Clone下面的函式):
class A
{
public:
virtual ~A() = default;
virtual std::unique_ptr<A> Clone() const = 0;
};
class B : public A
{
public:
std::unique_ptr<A> Clone() const override
{
return std::make_unique<B>(*this);
}
};
class X
{
public:
X(A const& param)
: abc(param.Clone())
{
}
// allow transferring an object stored in a unique_ptr to the object
template<class T> requires (std::is_base_of_v<A, T>)
X(std::unique_ptr<T>&& param)
: abc(std::move(param))
{}
private:
std::unique_ptr<A> abc;
};
請注意,如果您限制用戶將所有權轉移到 to 的子類A,X則根本不需要Clone功能。在這種情況下,您可以洗掉X::X(A const&)and 。Clone用戶仍然可以像這樣創建您的物件:
X x = std::make_unique<B>();
X x(std::make_unique<B>()); // alternative syntax for the above
uj5u.com熱心網友回復:
假設類在傳入后將X擁有,您可以這樣做:param
#include <iostream>
#include <memory>
class A { public: virtual ~A () {} };
class B : public A { public: ~B () { std::cout << "B destroyed"; } };
class X
{
public:
X (std::unique_ptr <A> ¶m) : m_param (std::move (param)) { }
private:
std::unique_ptr <A> m_param;
};
int main ()
{
std::unique_ptr <A> b = std::make_unique <B> ();
X x (b);
}
運行時,此代碼將列印B destroyed。請注意,要使其正常作業,A必須具有虛擬解構式。
param如果要與呼叫者和/或其他物件共享所有權,請std::shared_ptr改用(但這會產生更多開銷)。或者,正如@Remy 所說,如果您可以保證的生命周期param超過的生命周期x,您可以存盤一個原始指標(或參考)。
編輯:根據評論,類建構式的更好實作X是:
X (std::unique_ptr <A> &¶m) : m_param (std::move (param)) { }
然后你會這樣稱呼它:
X x { std::make_unique <B> (); }
這清楚地表明x擁有傳入的物件。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/428618.html
