[英]Why does a virtual function break my casting?
我正在努力擴展以下代碼:
#include <iostream>
class XmlTree {};
class Base
{
protected:
int var;
public:
Base(int var) : var(var) {}
virtual ~Base() {}
};
class Derived : public Base
{
public:
void SerializeTo(XmlTree& tree) const { std::cout << var << std::endl; }
void DeserializeFrom(const XmlTree& tree) { var = 2; }
};
void operator<<(XmlTree& tree, const Base& b) { static_cast<const Derived&>(b).SerializeTo(tree); }
void operator>>(const XmlTree& tree, Base& b) { static_cast<Derived&>(b).DeserializeFrom(tree); }
int main() {
Base b(1);
XmlTree tree;
tree << b;
tree >> b;
tree << b;
}
此代碼可以正常工作,並按預期先打印“ 1”,然后打印“ 2”。
但是現在我想實現一個這樣的接口:
class XmlInterface
{
public:
virtual void SerializeTo(XmlTree& tree) const = 0;
virtual void DeserializeFrom(const XmlTree& tree) = 0;
};
class Derived : public Base, public XmlInterface
{
public:
virtual void SerializeTo(XmlTree& tree) const override { std::cout << var << std::endl; }
virtual void DeserializeFrom(const XmlTree& tree) override { var = 2; }
};
TL; DR:如何使它起作用?
我嘗試使用dynamic_cast和虛擬析構函數使類具有多態性。 我還嘗試實現從Base到Derived的顯式下垂構造函數,但我失敗了。
PS:不能更改'Base'。
b
不是Derived
對象,因此將其強制轉換為Derived
是未定義的行為 。
在第一個示例中,正確的解決方案是將序列化方法移至Base
並將其虛擬/抽象化,以便Derived
可以覆蓋它們。 然后創建一個Derived
對象,並從運算符中刪除強制類型轉換:
#include <iostream>
class XmlTree {};
class Base
{
protected:
int var;
public:
Base(int var) : var(var) {}
virtual ~Base() {}
virtual void SerializeTo(XmlTree& tree) const = 0;
virtual void DeserializeFrom(const XmlTree& tree) = 0;
};
class Derived : public Base
{
public:
Derived(int var) : Base(var) {}
void SerializeTo(XmlTree& tree) const override { std::cout << var << std::endl; }
void DeserializeFrom(const XmlTree& tree) override { var = 2; }
};
void operator<<(XmlTree& tree, const Base& b) { b.SerializeTo(tree); }
void operator>>(const XmlTree& tree, Base& b) { b.DeserializeFrom(tree); }
int main() {
Derived d(1);
XmlTree tree;
tree << d;
tree >> d;
tree << d;
}
在第二個示例中執行類似的操作:
#include <iostream>
class XmlTree {};
class Base
{
protected:
int var;
public:
Base(int var) : var(var) {}
virtual ~Base() {}
};
class XmlInterface
{
public:
virtual void SerializeTo(XmlTree& tree) const = 0;
virtual void DeserializeFrom(const XmlTree& tree) = 0;
};
class Derived : public Base, public XmlInterface
{
public:
Derived(int var) : Base(var) {}
void SerializeTo(XmlTree& tree) const override { std::cout << var << std::endl; }
void DeserializeFrom(const XmlTree& tree) override { var = 2; }
};
void operator<<(XmlTree& tree, const XmlInterface& intf) { intf.SerializeTo(tree); }
void operator>>(const XmlTree& tree, XmlInterface& intf) { intf.DeserializeFrom(tree); }
int main() {
Derived d(1);
XmlTree tree;
tree << d;
tree >> d;
tree << d;
}
當將b
定義為Base
類型並調用運算符<<
,將操作數強制轉換為Derived&
,則您會產生未定義的行為,因為b
的類型不是Derived
。 未定義的行為意味着一切都可能發生,包括程序按預期工作。 稍微更改設置會產生不同的“不確定行為”,這就是您可以觀察到的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.