Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 多态引用类型_C++_Design Patterns_Polymorphism - Fatal编程技术网

C++ 多态引用类型

C++ 多态引用类型,c++,design-patterns,polymorphism,C++,Design Patterns,Polymorphism,我有一段简单的代码(命令模式),它并没有像预期的那样工作 通常,多态类型在被指针或引用操纵时可以工作。因此,如果Command是一个接口,m_Command是一个参考,那么SetCommand应该适用于不同具体类型的Command(例如,CommandLightOn和CommandGarageDoorOpen)?事实并非如此。使用CommandLightOn实例化SimpleRemote后,SetCommand完全无效。在本例中,尝试将基础对象更改为CommandGarageDoorOpen没有

我有一段简单的代码(命令模式),它并没有像预期的那样工作

通常,多态类型在被指针或引用操纵时可以工作。因此,如果
Command
是一个接口,
m_Command
是一个参考,那么
SetCommand
应该适用于不同具体类型的
Command
(例如,
CommandLightOn
CommandGarageDoorOpen
)?事实并非如此。使用
CommandLightOn
实例化
SimpleRemote
后,
SetCommand
完全无效。在本例中,尝试将基础对象更改为
CommandGarageDoorOpen
没有错误,但也没有效果

如果将
SimpleRemote
中的
m_命令更改为指针类型,则可以正常工作。
所以问题是为什么引用类型在这种情况下不能工作

class SimpleRemote
{
public:
    SimpleRemote( Command& command ) : m_command{ command } {}

    void SetCommand( Command& command )
    {
        m_command = command;  //<-- broken
    }

    void ButtonPressed()
    {
        m_command.execute();
    }

private:
    Command& m_command;
};
class SimpleRemote
{
公众:
SimpleRemote(Command&Command):m_Command{Command}{}
void SetCommand(命令和命令)
{

m_command=command;//引用必须初始化,但无法更新。很遗憾,编译器不会警告您!您可以看到解释

必须使用指针而不是引用:

class SimpleRemote
{
public:
    SimpleRemote( Command& command ) : m_command{ &command } {}

    void SetCommand( Command& command )
    {
        m_command = &command;
    }

    void ButtonPressed()
    {
        m_command->execute();
    }

private:
    Command* m_command;
};

这里有两个问题。首先,C++中的引用不像指针那样可回退。这意味着这样的代码:

int a = 1;
int& ref = a; // ref refers to a
int b = 2;
ref = b; // ref STILL referes to a
留给您的是
a==2
b==2
。这就是它的工作方式

第二个问题是所谓的对象切片。如果你仔细考虑一下,唯一合乎逻辑的是,既然引用与多形性代码一起工作,像这样是合法的:

class A{
public:
    virtual void foo() = 0;
};

class B : public A {
public:
    void foo() override {}
};

class C : public A {
public:
    void foo() override {}
};

int main() {
    auto c = C{};
    A& a = c;
    auto b = B{};
    a = b;
}
这是怎么回事?嗯,对象
c
A
部分将根据编译器默认生成的
A::operator=
替换为对象B的
A
部分。您可以在
A::operator=
中输入一些输出来确认我在这里说的话

把这两个东西放在一起,你就有问题了。如何避免它呢?首先,如果你想重新绑定引用,可以使用<代码> STD::RealthyOnWrpPult<代码>或普通指针。第二,考虑声明<代码>运算符=()。

为您的接口/抽象类删除。这将使编译器在尝试错误地切片对象时产生错误

建议修复后的部分代码:

class Command
{
public:
    Command& operator=(const Command&) = delete;
    virtual void execute() = 0;
    virtual ~Command() = default; // <-- this is good practice
};
////............... rest of code here
class SimpleRemote
{
public:
    SimpleRemote(Command& command) : m_command{ command } {}

    void SetCommand(Command& command)
    {
        m_command = command;
    }

    void ButtonPressed()
    {
        m_command.get().execute();
    }

private:
    std::reference_wrapper<Command> m_command;
};
class命令
{
公众:
命令和运算符=(常量命令&)=删除;
虚空执行()=0;

virtual~Command()=default;//引用只能初始化一次,之后不能更改引用的对象。此处
m_Command=Command;//@rafix07谢谢。因此,问题是重新分配引用,而不是多态类型。不过,我想知道为什么这样的错误不会出现错误。
class Command
{
public:
    Command& operator=(const Command&) = delete;
    virtual void execute() = 0;
    virtual ~Command() = default; // <-- this is good practice
};
////............... rest of code here
class SimpleRemote
{
public:
    SimpleRemote(Command& command) : m_command{ command } {}

    void SetCommand(Command& command)
    {
        m_command = command;
    }

    void ButtonPressed()
    {
        m_command.get().execute();
    }

private:
    std::reference_wrapper<Command> m_command;
};