我有一個Accessor類定義了我與其他類的介面和這個Accessor類中的多個基類物件,實作了各種風格的東西。
class Accessor
{
std::shared_ptr<Base> object1;
std::shared_ptr<Base> object2;
}
Accessor當然,該類實作的不僅僅是對不同物件的呼叫,還有一個特定的函式,它確實只將函式呼叫重定向到其中一個物件。
現在的問題是,這個特定的函式應該只在一個派生類中實作,當使用Accessor該類呼叫函式時,已知特定物件始終是實作此方法的派生類。目前,我正在定義一個“空”基類方法,并僅在提到的派生類中覆寫它。
但是,我不喜歡這種方法有兩個原因:第一,從設計的角度來看它看起來很丑;第二,我仍然有一個virtual函式呼叫(這里討論的函式在回圈的熱路徑中)。
總之,代碼的最小版本如下所示:
class Base
{
virtual void f() const { std::cout << "Dummy implementation!\n";}
};
class Derived1 : Base
{
void f() const override { std::cout << "Implementing the actual thing!\n";}
};
class Derived2 : Base
{
// Carrying the dummy implementation of the base class
};
class Accessor
{
std::shared_ptr<Base> object1;
std::shared_ptr<Base> object2;
// When calling this function, we know that we actually
// call object1 of type `Derived1`. Still, there might be
// cases where object1 has a different type, but then we don't
// call this function
void f() const { object1->f();}
}
整個描述可能在某種程度上表明整體設計不是最佳選擇。但是,也許這里有其他選項可以重新設計問題,使虛函式呼叫消失,代碼更好地反映實際情況。
uj5u.com熱心網友回復:
如果您確定object_1始終指向 a Derived1,則將其設為a std::shared_ptr<Derived1> object1。如果 的唯一目的Base::f()是 for Derived1,請將其設為非虛擬并將其從不需要它的類中洗掉。
但是,如果這些假設之一不正確,請保持原樣:
Derived1在呼叫非虛函式之前進行額外的測驗以檢查類是否比直接呼叫虛函式更有效。如果你不相信我,做一個基準。此外,如果將來您對 有更進一步的專業化Derived1,與略有不同的f(),您不必擔心。假設它總是
Derived1并且只是靜態向下轉換是有風險的。如前所述,如果您非常確定,只需將其宣告為(轉到第一段),并在 初始化 時進行(安全)向下轉換object_1。
備注:雖然f()在大多數情況下開始使用 a 似乎很奇怪,但實際上這是將多型與tell一起使用時的常見做法,不要問范式。一個非常典型的例子是使用模板方法模式時。
uj5u.com熱心網友回復:
您可以使用 避免基類和虛擬方法std::variant,但它比虛擬函式呼叫慢一些。您可以測驗該Derived1型別是否在variant.
class Derived1
{
public:
void f(size_t i) { _i; }
private:
size_t _i {0};
};
class Derived2
{
public:
};
class Accessor
{
public:
template<typename S>
void add_one (std::shared_ptr<S> val) {
object1 = val;
}
// When calling this function, we know that we actually
// call object1 of type `Derived1`. Still, there might be
// cases where object1 has a different type, but then we don't
// call this function
void f(size_t i) const {
// you can check the type with this
//if (std::holds_alternative<std::shared_ptr<Derived1>>(object1)) {
std::get<std::shared_ptr<Derived1>>(object1)->f (i);
//}
}
public:
std::variant<std::shared_ptr<Derived1>, std::shared_ptr<Derived2>> object1;
};
int main ()
{
Accessor obj;
obj.add_one (std::make_shared<Derived2>());
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/402952.html
標籤:
上一篇:用于構造子類的Python類方法
下一篇:如何在java中加入兩個地圖?
