如何在 C++ 中正确继承抽象 class?

How to inherit from an abstract class properly in C++?

我找不到适合这个问题的主题,因为我没有收到正确的错误消息。

我正在尝试为一家主要提供披萨和其他食物(意大利面、鸡翅等)的餐厅创建一个管理系统。我想让员工使用这个系统。我创建了一个名为 Foods 的摘要 class,可以用于其他食物继承。到目前为止,我已经创建了一个继承自 Foods 的 class,名为 Pizza。下面是我的代码。

PS: 我用 namespaces 分别组织食物和工作人员。据我所知,有些人不推荐 namespace 如果您是其中之一,我深表歉意。

interfaces.h

#include <vector>
#include <string>

namespace foods{
    class Food{
        double price;
        // since the sauces and drinks are given with foods.
        static const std::vector<std::string> sauces;
        static const std::vector<std::string> drinks;
    public:
        virtual int retPrice() = 0;
        virtual void ask() = 0; // ask user what to add
        virtual ~Food() = default;
    };
    const std::vector<std::string> Food::sauces = {"Blue cheese", "Garlic", "Honey BBQ", "Marinara"};
    const std::vector<std::string> Food::drinks = {"Pepsi", "Mountain Dew", "Coca Cola"};

    class Pizza: public Food{
        const double price;
        const std::string pizzaType; // whether it is chicken, beef, etc.
        const std::string size; // small, medium or large
    
        int crust = 1; // how crust it is from 1-5
        std::vector<std::string> toppings; // to store toppings
    public:
        Pizza(): price(15), pizzaType(" "), size(" "){}
        int retPrice() override; // the price should change according to the type
        void ask() override; // ask the customer for a pizza

        void createACustom(); // create a custom pizza with desired toppings
    };
};

functions.cpp

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

namespace foods{
    int Pizza::retPrice(){
        return (price+5);
    }
    void Pizza::ask(){
        std::cout << "Hello World!";
    }
}

test.cpp

#include "interfaces.h"

int main(){
    foods::Pizza* pizza = new foods::Pizza();
}

我收到以下错误。

/usr/bin/ld: /tmp/ccQRR5B8.o: warning: relocation against `_ZTVN5foods5PizzaE' in read-only section `.text._ZN5foods5PizzaC2Ev[_ZN5foods5PizzaC5Ev]'
/usr/bin/ld: /tmp/ccQRR5B8.o: in function `foods::Pizza::Pizza()':
test.cpp:(.text._ZN5foods5PizzaC2Ev[_ZN5foods5PizzaC5Ev]+0x2b): undefined reference to `vtable for foods::Pizza'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status

我尝试使用关键字 override 并创建了一个默认解构器,但似乎没有任何效果。我想知道此错误消息的含义及其解决方案。除此之外,什么是 vtable?

感谢您的宝贵时间和回答。

编辑 1

我用 g++ -Wall -Wextra test.cpp functions.cpp -o test 编译了它,这是错误的,然后我做了 g++ -Wall -Wextra test.cpp functions.cpp -o test,但出现了以下错误。

/usr/bin/ld: /tmp/ccmv2G17.o:(.bss+0x0): multiple definition of `foods::Food::sauces[abi:cxx11]'; /tmp/ccuBNQjX.o:(.bss+0x0): first defined here
/usr/bin/ld: /tmp/ccmv2G17.o:(.bss+0x20): multiple definition of `foods::Food::drinks[abi:cxx11]'; /tmp/ccuBNQjX.o:(.bss+0x20): first defined here
collect2: error: ld returned 1 exit status

为什么说它有多个定义?

您需要在 functions.cpp 而不是 interfaces.h.

中实现静态成员变量 saucesdrinks

functions.cpp

namespace foods {
  int Pizza::retPrice() {
    return (price + 5);
  }
  void Pizza::ask() {
    std::cout << "Hello World!";
  }

  // implement the static variables here.
  const std::vector<std::string> Food::sauces = { "Blue cheese", "Garlic", "Honey BBQ", "Marinara" };
  const std::vector<std::string> Food::drinks = { "Pepsi", "Mountain Dew", "Coca Cola" };
}

并将它们从 interfaces.h 中移除。

如果您在 interfaces.h 中实现它们,它们最终会在包含 interfaces.h.

的每个 .cpp 文件中实现

这与在 .h 文件中定义全局变量基本相同。