C++ 为什么虚拟功能会破坏我的角色?

C++ 为什么虚拟功能会破坏我的角色?,c++,casting,virtual,downcast,C++,Casting,Virtual,Downcast,我正在努力扩展以下代码: #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 { s

我正在努力扩展以下代码:

#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;
}
#包括
类XmlTree{};
阶级基础
{
受保护的:
int-var;
公众:
Base(int-var):var(var){}
虚拟~Base(){}
};
派生类:公共基
{
公众:

void SerializeTo(XmlTree&tree)const{std::cout
b
不是
派生的
对象,因此将其强制转换为
派生的
未定义的行为

在第一个示例中,正确的解决方案是将序列化方法移动到
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;
}
#包括
类XmlTree{};
阶级基础
{
受保护的:
int-var;
公众:
Base(int-var):var(var){}
虚拟~Base(){}
虚拟空序列化为(XmlTree&tree)常量=0;
虚拟void反序列化自(const-XmlTree&tree)=0;
};
派生类:公共基
{
公众:
派生(int-var):基(var){}

void SerializeTo(XmlTree&tree)const override{std::cout
b
不是
派生的
对象,因此将其强制转换为
派生的
未定义的行为

在第一个示例中,正确的解决方案是将序列化方法移动到
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;
}
#包括
类XmlTree{};
阶级基础
{
受保护的:
int-var;
公众:
Base(int-var):var(var){}
虚拟~Base(){}
虚拟空序列化为(XmlTree&tree)常量=0;
虚拟void反序列化自(const-XmlTree&tree)=0;
};
派生类:公共基
{
公众:
派生(int-var):基(var){}

void序列化为(XmlTree&tree)常量重写{std::cout当定义
b
Base
类型时,调用操作符
当定义
b
Base
类型时,调用操作符
b
不是
派生的
对象,因此将其强制转换为
派生的
是未定义的行为。添加
虚拟的
帮助y使存在的问题变得明显。这不是问题的原因。
b
不是
派生的
对象,因此将其强制转换为
派生的
是未定义的行为。添加
虚拟的
有助于使存在的问题变得明显。这不是问题的原因。遗憾的是,更改“Base”不是一个选项。@PanicSheep:那么你呢除非您选择
XmlInterface
路线,否则您的运气不好。您最初显示的代码将不起作用,您需要按照说明更正设计。遗憾的是,更改“Base”不是一个选项。@PanicSheep:那么您就运气不好,除非您选择
XmlInterface
路线。您最初显示的代码将不起作用,您需要更正按所述纠正设计。
#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;
}