如何在从抽象基派生的类中实现相同的方法?
How to implement the same method in classes derived from an abstract base?
我有一个抽象类Job
和其他实现它的类,如下所示:
Waiter
和Builder
,它们都以相同的方式实现我的函数。
例如:
Waiter::changeScore()
{
score += top_score;
}
如何防止这种代码重复?
约束:
我想保持
Job
抽象。每个
Waiter
或Builder
都有自己的top_score
值(它在同一类的类和对象之间有所不同(。
并非抽象类的所有成员函数都需要是纯虚拟的(只要至少有一个(。您的changeScore
成员是作为"真正的"基类函数的理想候选项。此外,它不仅不需要是纯virtual
,甚至根本不需要virtual
(除非你想让你的多态性改变指向派生类的指针将看到的内容,对于该函数(。
由于每个类(或对象(都有自己的top_score
值(如您所述(,因此该(数据(成员也可以是"抽象"基类的一部分。
您甚至可以在基类中添加单个"虚拟"纯虚函数(该函数从不打算使用,即使是派生类(,以确保不会意外创建实例。例如,您的Job
类可以有一个成员:
virtual int Dummy() = 0;
然后,任何派生类都必须具有该类的重写(无论多么微不足道(,否则编译器将不允许声明该类的实例。因此,您的Waiter
类需要以下内容:
int Dummy override { return 1; }
以下代码示例可能有助于/演示该想法:
#include <iostream>
#include <memory> // So we can use smart pointers
class Job {
public:
int score{ 0 }, top_score{ 0 };
public:
Job() { }
virtual ~Job() = default;
virtual void Dummy() = 0; // This is sufficient to make the class abstract!
void changeScore() {
score += top_score;
}
virtual void showName() {
std::cout << "Generic Job" << std::endl;
}
};
class Waiter : public Job {
public:
Waiter(int top = 5) { top_score = top; }
~Waiter() override = default;
void Dummy() override { } // We need this in order to use Waiter
void showName() override {
std::cout << "Waiter" << std::endl;
}
};
class Builder : public Job {
public:
Builder(int top = 10) { top_score = top; }
~Builder() override = default;
void Dummy() override { } // We need this in order to use Builder
void showName() override {
std::cout << "Builder" << std::endl;
}
};
int main()
{
Waiter w{ 6 }; // OK - uses explicit value for 'top' parameter
Builder b; // OK - uses default value for 'top' parameter
// Job j; // ERROR - Cannot instantiate abstract class
w.changeScore();
b.changeScore();
std::cout << w.score << std::endl;
std::cout << b.score << std::endl;
// Also, using pointers...
// Job* pj = new Job; // ERROR - Cannot instantiate abstract class
Job* pw = new Waiter; // OK - Now we can make use of polymorphism...
Job* pb = new Builder; // ...with either of these 2 "Job" pointers!
pw->showName();
pb->showName();
delete pw;
delete pb;
// Polymorphism also works with smart pointers (which you SHOULD be using) ...
// std::unique_ptr<Job> upj = std::make_unique<Job>(); // ERROR - Allocating an object of abstract class
std::unique_ptr<Job> upw = std::make_unique<Waiter>(15);
upw->changeScore();
std::cout << upw->score << ": ";
upw->showName();
std::unique_ptr<Job> upb = std::make_unique<Builder>(42);
upb->changeScore();
std::cout << upb->score << ": ";
upb->showName();
return 0;
}
可以在基类中定义方法:
现场演示
class Job {
private:
int score;
int top_score;
protected:
//protected constructor to be inherited by derived classes
Job(int top_score) : top_score(top_score) {}
//one pure virtual method is enough to make the class abstract
virtual void some_method() = 0;
public:
void changeScore() { //single method implementation
score += top_score;
}
//to use polymorphism you must use a virtual destructor, unless you use shared_ptr
virtual ~Job(){}
};
class Waiter : public Job {
public:
Waiter(int top_score) : Job(top_score) {}
// pure virtual methods must be overridden in all derived classes
void some_method() override{}
};
class Builder : public Job {
public:
Builder(int top_score) : Job(top_score) {}
void some_method() override{}
};
changeScore()
将在抽象类中实现,并且可供所有派生类使用。
Waiter w(10); //top_score 10
Buider b(20); // top_score 20
b.changeScore();
w.changeScore();
你可以使changeScore
方法成为纯虚拟方法,并提供一个实现。这看起来像这样:
class Job {
int score{0};
int top_score{0};
public:
virtual void changeScore() = 0;
};
void Job::changeScore()
{
score += top_score;
}
然后,可以在子类中调用Job
基类的changeScore
方法,如下所示:
class Waiter : public Job {
public:
virutal void changeScore() override {
Job::changeScore();
}
};
这样,如果要更改changeScore
,则不需要更改子类中的所有实现,而只需更改Job
类中的实现即可。 这样,您不需要任何虚拟方法,并且Job
类仍然是抽象的,而子类中的覆盖是微不足道的,如果您想更改它,您只有一个实现。
编辑: 如果您想知道这个override
关键字的来源,它在 C++11 中介绍。由于我不知道您使用的是哪个C++版本,因此我只想指出这一点。 您可以在此处阅读有关覆盖说明符的信息
编辑二: 关于子类有自己的top_score
,你应该通过这些子类的构造函数来设置它。 喜欢这个:
class Job {
protected:
int top_score{0};
Job(top) : top_score(top) {}
...
};
class Waiter : public Job {
public:
Waiter(int top): Job(top) {}
...
};
这样,每个子类都有自己的top_score
版本
编辑三: 将它们放在一起,这些类将如下所示:
class Job {
protected:
int score{0};
int top_score{0};
Job(top) : top_score(top) {}
public:
virtual void changeScore() = 0;
};
void Job::changeScore()
{
score += top_score;
}
class Waiter : public Job {
public:
Waiter(int top): Job(top) {}
virutal void changeScore() override {
Job::changeScore();
}
};
- 实现无开销push_back的最佳方法是什么
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 这是实现图形的坏方法吗
- 在 c++ 中实现嵌套循环的更短方法吗?
- 如何实现 Front() 方法以返回模板化双向链表C++的第一个元素?
- 如何在从抽象基派生的类中实现相同的方法?
- C++数组队列实现方法错误
- 有没有一种通用的方法来实现不变量
- 'using namespace'实现细节的便捷方法(仅标头库)?
- 使用非递归插入方法实现 AVL 树
- C ++类型特征:确保子类实现方法
- 实现基于数字值(正、负、零)的条件表达式的最佳方法
- 在C++上实现高斯赛德尔迭代方法
- C++方法实现:是否可以避免每次都键入类名?
- 如何知道C2259 VS 2017错误未实现哪种方法?
- C++强制在子类中实现方法,但具有不同的签名
- 避免在每个派生类中重新实现方法调用
- C :执行模板类型实现方法
- 在C++中实现方法时继承不起作用
- 还有更好的实现方法吗?