如何在 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
.
中实现静态成员变量 sauces
和 drinks
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 文件中定义全局变量基本相同。
我找不到适合这个问题的主题,因为我没有收到正确的错误消息。
我正在尝试为一家主要提供披萨和其他食物(意大利面、鸡翅等)的餐厅创建一个管理系统。我想让员工使用这个系统。我创建了一个名为 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
.
sauces
和 drinks
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
.
这与在 .h 文件中定义全局变量基本相同。