未解析的外部符号如何解决?抽象类

Unresolved External Symbol how to fix it? abstract class

提问人:Philipp Peter 提问时间:8/23/2021 更新时间:8/23/2021 访问量:1193

问:

这是我的抽象类 Storestate.h:

#ifndef STORESTATE_H_
#define STORESTATE_H_

class Store;
class StoreState
{
public:
    virtual void Close(Store&);
    virtual void Open(Store&);
    virtual void Sell(Store&);
};

#endif

派生类头文件 ConcreteStateOpened.h:

#ifndef CONCRETESTATEOPENED_H_
#define CONCRETESTATEOPENED_H_
#include "StoreState.h"
#include "Store.h"

class ConcreteStateOpened : public StoreState
{
public:
    ConcreteStateOpened() {}
    void Open(Store&) override;
    void Close(Store&) override;
    void Sell(Store&) override;
};

#endif

Dervied 类 cpp 文件 ConcreteStateOpened.cpp:

#include "ConcreteStateOpened.h"
#include <iostream>

using namespace std;

void ConcreteStateOpened::Open(Store &store)
{
    cout << store.Name << " is already opened!" << endl;
}
void ConcreteStateOpened::Close(Store &store)
{
    store.State = ConcreteStateOpened();
}
void ConcreteStateOpened::Sell(Store &store)
{
    std::cout << "Sell Opened";
}

我不知道如何解决这个问题。我尝试删除覆盖关键字以及虚拟关键字。甚至删除定义等。我只是需要专业人士的帮助:,)

以下是未解决的外部符号错误:

1>ConcreteStateOpened.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Close(class Store &)" (?Close@StoreState@@UAEXAAVStore@@@Z)
1>Data.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Close(class Store &)" (?Close@StoreState@@UAEXAAVStore@@@Z)
1>StateStore.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Close(class Store &)" (?Close@StoreState@@UAEXAAVStore@@@Z)
1>ConcreteStateOpened.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Open(class Store &)" (?Open@StoreState@@UAEXAAVStore@@@Z)
1>Data.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Open(class Store &)" (?Open@StoreState@@UAEXAAVStore@@@Z)
1>StateStore.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Open(class Store &)" (?Open@StoreState@@UAEXAAVStore@@@Z)
1>ConcreteStateOpened.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Sell(class Store &)" (?Sell@StoreState@@UAEXAAVStore@@@Z)
1>Data.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Sell(class Store &)" (?Sell@StoreState@@UAEXAAVStore@@@Z)
1>StateStore.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall StoreState::Sell(class Store &)" (?Sell@StoreState@@UAEXAAVStore@@@Z)
1>D:\Local-Git-Repos\DesignPatterns\StateC++\StateStore\Debug\StateStore.exe : fatal error LNK1120: 3 unresolved externals
C++ 继承多 态性 抽象类 未解析 - 外部

评论


答:

-1赞 Michael 8/23/2021 #1

您可能需要将 virtual 添加到具体的类方法中

#ifndef CONCRETESTATEOPENED_H_
#define CONCRETESTATEOPENED_H_
#include "StoreState.h"
#include "Store.h"

class ConcreteStateOpened : public StoreState
{
public:
    ConcreteStateOpened() {}
    virtual void Open(Store&) override;
    virtual void Close(Store&) override;
    virtual void Sell(Store&) override;
};

#endif

评论

1赞 aschepler 8/23/2021
不,派生类中的函数自动是虚拟的,只要它们与基类虚拟函数具有相同的名称和签名,无论 and/or 是否存在。由于声明不可能不是虚拟的,因此许多 C++ 程序员也认为编写也是多余的。virtualoverrideoverridevirtual
1赞 Pepijn Kramer 8/23/2021 #2

你没有使抽象库中的方法成为纯粹的虚拟方法。 此外,您还应该添加:公共虚拟析构函数、受保护的默认构造函数和删除复制/移动/赋值构造函数

#ifndef STORESTATE_H_
#define STORESTATE_H_

class Store;
class StoreState
{
public:
    virtual ~StoreState() = default;
    StoreState(const StoreState&) = delete;
    StoreState(StoreState&&) = delete;
    StoreState& operator=(const StoreState&) = delete;

    virtual void Close(Store&) = 0;
    virtual void Open(Store&) = 0;
    virtual void Sell(Store&) = 0;
protected:
    StoreState() = default; // prevent accidental creation
};

#endif
0赞 Vlad from Moscow 8/23/2021 #3

对于初学者来说,您提供的代码中没有抽象类,因为该类不包含纯虚函数。StoreState

来自 C++ 20 标准(11.7.3 抽象类)

2 虚函数被指定为纯虚函数,使用 类中函数声明中的纯说明符 (11.4) 定义。[注意:这样的功能可能是继承的:见下文。 尾注] 如果一个类至少有一个纯类,则该类是抽象类 虚拟功能。[注意:抽象类只能用作 其他类的基类;抽象类的任何对象都不能 创建,但作为派生自它的类的子对象(6.2、11.4)除外。— 尾注] 纯虚函数只有在调用时才需要定义, 或者好像使用 (11.4.6),qualified-id 语法

您需要提供类中声明的虚函数的定义,或者使它们成为纯虚函数,例如StoreState

class StoreState
{
public:
    virtual void Close(Store&) = 0;
    virtual void Open(Store&) = 0;
    virtual void Sell(Store&) = 0;
};

即使一个函数被声明为纯虚函数,但如果需要,你可以提供它的定义(在它被声明为纯虚函数的类定义之外)。

请注意,当你有多态类时,你应该将析构函数也声明为虚拟的。例如

class StoreState
{
public:
    virtual ~StoreState() = default;

    virtual void Close(Store&) = 0;
    virtual void Open(Store&) = 0;
    virtual void Sell(Store&) = 0;
};
0赞 aschepler 8/23/2021 #4

你实际上不是抽象的。您已将 、 声明为具有定义的实际虚函数。要声明该类中没有定义的虚函数,请使用 “pure virtual” 语法 。StoreStateCloseOpenSell= 0

此外,多态类类型的最佳做法是具有虚拟析构函数。根据五法则,当您声明析构函数时,请务必考虑复制/移动构造函数和复制/移动赋值。对于接口类,通常最好将其设置为不可复制和不可分配。

class StoreState
{
public:
    StoreState() = default;
    StoreState(const StoreState&) = delete;
    StoreState& operator=(const StoreState&) = delete;
    virtual ~StoreState() = default;

    virtual void Close(Store&) = 0;
    virtual void Open(Store&) = 0;
    virtual void Sell(Store&) = 0;
};