如何在从抽象基派生的类中实现相同的方法?

How to implement the same method in classes derived from an abstract base?

本文关键字:实现 方法 抽象 派生      更新时间:2023-10-16

我有一个抽象类Job和其他实现它的类,如下所示:

WaiterBuilder,它们都以相同的方式实现我的函数。

例如:

Waiter::changeScore()
{
score += top_score;
}

如何防止这种代码重复?

约束:

  1. 我想保持Job抽象。

  2. 每个WaiterBuilder都有自己的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();
}
};