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;
};