Virtual Functions C++: virtual function already has a body
Virtual Functions C++: virtual function already has a body
我在实现在不同 header 的另外两个 class 抽象 class 处声明的虚函数时遇到问题。
当我在 Class ProtocolLogin 中实现已经在 ProtocolGame 实现的虚函数 "parsePacket" 时,编译器 returns "function already has a body"。
Error 1 error LNK2005: "private: virtual void __cdecl ProtocolGame::parsePacket(class NetworkMessage &)" (?parsePacket@ProtocolGame@@EEAAXAEAVNetworkMessage@@@Z) already defined in protocolgame.obj
Error 2 error LNK2001: unresolved external symbol "public: virtual void __cdecl ProtocolLogin::parsePacket(class NetworkMessage &)" (?parsePacket@ProtocolLogin@@UEAAXAEAVNetworkMessage@@@Z)
然后我尝试创建一个名为 parseWater 的新虚函数,它将仅在 Class ProtocolLogin 编译器 returns me "function need to be declared at ProtocolGame" 上实现,但如果我这样做,我又得到了:"function already has a body"。所以,我干脆不跟了。请帮助我理解:)
就像一个无尽的圆圈。
class Protocol (Header File 1)
{
public:
explicit Protocol(Connection_ptr connection) : m_connection(connection)
virtual ~Protocol() = default;
// non-copyable
Protocol(const Protocol&) = delete;
Protocol& operator=(const Protocol&) = delete;
virtual void parsePacket(NetworkMessage&) {}
void onRecvMessage(NetworkMessage& msg); // Function that calls parsePacket
virtual void onRecvFirstMessage(NetworkMessage& msg) = 0;
class ProtocolGame final : public Protocol (Header File 2)
{
public:
// static protocol information
enum {server_sends_first = true};
enum {protocol_identifier = 0}; // Not required as we send first
enum {use_checksum = true};
static const char* protocol_name() {
return "gameworld protocol";
}
explicit ProtocolGame(Connection_ptr connection);
private:
void parsePacket(NetworkMessage& msg) final; //implementation //Works
void onRecvFirstMessage(NetworkMessage& msg) final; //implementation //Works
class ProtocolLogin final : public Protocol (Header File 3)
{
public:
// static protocol information
enum {server_sends_first = false};
enum {protocol_identifier = 0x01};
enum {use_checksum = true};
static const char* protocol_name() {
return "login protocol";
}
explicit ProtocolLogin(Connection_ptr connection) : Protocol(connection) {}
void onRecvFirstMessage(NetworkMessage& msg); //work
void parsePacket(NetworkMessage& msg); // dont work
我不是很熟悉 C++11,但是你派生的 classes 想要实现虚函数也需要将它们的实现声明为 virtual
.我不认为 final
不需要声明 virtual
。 (事实上, 将 non-virtual 函数声明为 final
是错误的)
如果您注意到,您的 parent class 定义了 parseWater()
和 virtual
,但没有 parseAlchohol()
,这就是为什么您的 ProtocolAlchohol
class 声明 void parseAlchohol() final;
没有问题,ProtocolWater
声明 void parseWater() final;
有问题
p.s., 如果你明确引用 childclass 中的概念(即水和酒精),我不确定你是否正确地推导和 OOP您的 parent class,以及基于水和酒精的命名功能。
编辑:别介意我的第一段。我想我总是按照惯例这样做,但没有意识到这是没有必要的。
parseWater
是唯一声明为 final
.
的最终函数
所有其他 final
函数在某处没有 virtual
关键字。
正如 StoryTeller 指出的那样 "You don't have to restate the virtual specifier in derived classed."
既然我们在讨论在派生的classess中使用virtual
,我想声明一下。不幸的是,在我看来,C++ 在这方面是不一致的。您可能 'restate' 虚拟,也可能不虚拟。更糟糕的是,当函数在基 class 中不是虚函数时,您可以将其设为虚函数 - 这可能会给代码 reader 指示函数是虚函数 - 错误指示。
如果 C++ 实际上强制使用 virtual - 在所有虚函数的重新定义中都需要它并禁止在非虚拟函数上重新定义它,那么代码维护者会容易得多。
我在实现在不同 header 的另外两个 class 抽象 class 处声明的虚函数时遇到问题。
当我在 Class ProtocolLogin 中实现已经在 ProtocolGame 实现的虚函数 "parsePacket" 时,编译器 returns "function already has a body"。
Error 1 error LNK2005: "private: virtual void __cdecl ProtocolGame::parsePacket(class NetworkMessage &)" (?parsePacket@ProtocolGame@@EEAAXAEAVNetworkMessage@@@Z) already defined in protocolgame.obj
Error 2 error LNK2001: unresolved external symbol "public: virtual void __cdecl ProtocolLogin::parsePacket(class NetworkMessage &)" (?parsePacket@ProtocolLogin@@UEAAXAEAVNetworkMessage@@@Z)
然后我尝试创建一个名为 parseWater 的新虚函数,它将仅在 Class ProtocolLogin 编译器 returns me "function need to be declared at ProtocolGame" 上实现,但如果我这样做,我又得到了:"function already has a body"。所以,我干脆不跟了。请帮助我理解:)
就像一个无尽的圆圈。
class Protocol (Header File 1)
{
public:
explicit Protocol(Connection_ptr connection) : m_connection(connection)
virtual ~Protocol() = default;
// non-copyable
Protocol(const Protocol&) = delete;
Protocol& operator=(const Protocol&) = delete;
virtual void parsePacket(NetworkMessage&) {}
void onRecvMessage(NetworkMessage& msg); // Function that calls parsePacket
virtual void onRecvFirstMessage(NetworkMessage& msg) = 0;
class ProtocolGame final : public Protocol (Header File 2)
{
public:
// static protocol information
enum {server_sends_first = true};
enum {protocol_identifier = 0}; // Not required as we send first
enum {use_checksum = true};
static const char* protocol_name() {
return "gameworld protocol";
}
explicit ProtocolGame(Connection_ptr connection);
private:
void parsePacket(NetworkMessage& msg) final; //implementation //Works
void onRecvFirstMessage(NetworkMessage& msg) final; //implementation //Works
class ProtocolLogin final : public Protocol (Header File 3)
{
public:
// static protocol information
enum {server_sends_first = false};
enum {protocol_identifier = 0x01};
enum {use_checksum = true};
static const char* protocol_name() {
return "login protocol";
}
explicit ProtocolLogin(Connection_ptr connection) : Protocol(connection) {}
void onRecvFirstMessage(NetworkMessage& msg); //work
void parsePacket(NetworkMessage& msg); // dont work
我不是很熟悉 C++11,但是你派生的 classes 想要实现虚函数也需要将它们的实现声明为 将 non-virtual 函数声明为 virtual
.我不认为 final
不需要声明 virtual
。 (事实上,final
是错误的)
如果您注意到,您的 parent class 定义了 parseWater()
和 virtual
,但没有 parseAlchohol()
,这就是为什么您的 ProtocolAlchohol
class 声明 void parseAlchohol() final;
没有问题,ProtocolWater
声明 void parseWater() final;
p.s., 如果你明确引用 childclass 中的概念(即水和酒精),我不确定你是否正确地推导和 OOP您的 parent class,以及基于水和酒精的命名功能。
编辑:别介意我的第一段。我想我总是按照惯例这样做,但没有意识到这是没有必要的。
parseWater
是唯一声明为 final
.
所有其他 final
函数在某处没有 virtual
关键字。
正如 StoryTeller 指出的那样 "You don't have to restate the virtual specifier in derived classed."
既然我们在讨论在派生的classess中使用virtual
,我想声明一下。不幸的是,在我看来,C++ 在这方面是不一致的。您可能 'restate' 虚拟,也可能不虚拟。更糟糕的是,当函数在基 class 中不是虚函数时,您可以将其设为虚函数 - 这可能会给代码 reader 指示函数是虚函数 - 错误指示。
如果 C++ 实际上强制使用 virtual - 在所有虚函数的重新定义中都需要它并禁止在非虚拟函数上重新定义它,那么代码维护者会容易得多。