簡體   English   中英

如何在從抽象基派生的類中實現相同的方法?

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

我有一個抽象的 class Job和其他實現它的類,例如:

WaiterBuilder ,他們都以同樣的方式實現了我的 function。

例如:

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

如何防止這種代碼重復?

約束:

  1. 我想保持Job的抽象。

  2. 每個WaiterBuilder都有自己的top_score值(在類和同一類的對象之間有所不同)。

並非抽象 class 的所有成員函數都必須是純虛函數(只要至少有一個是)。 您的changeScore成員是作為“真實”基礎 class function 的理想人選。 此外,它不僅不需要是virtual ,甚至根本不需要是virtual (除非您希望多態性更改指向派生 class 的指針將看到的內容,對於該函數)。

由於每個 class (或對象)都有自己的top_score(如您所述),因此該(數據)成員也可以是“抽象”基礎 class 的一部分。

您甚至可以在基礎 class 中添加一個“虛擬”純虛擬 function(即使派生類也不打算使用它),只是為了確保不會意外創建實例。 例如,您的Job class 可能有一個成員:

    virtual int Dummy() = 0;

然后,任何派生的 class必須有一個覆蓋(無論多么微不足道),否則編譯器將不允許您聲明該 class 的實例。 所以,你的Waiter class 需要類似的東西:

    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 中定義方法:

現場演示

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()將在抽象 class 中實現,並可供所有派生類使用。

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 base class 的changeScore方法:

class Waiter : public Job {
public:
  virutal void changeScore() override {
    Job::changeScore();
  }
};

這樣,如果要更改changeScore ,則不需要更改子類中的所有實現,而只需更改Job class 中的實現即可。 這樣您就不需要任何虛擬方法,並且Job class 仍然是抽象的,而子類中的覆蓋是微不足道的,如果您想更改它,您只有一個實現。

編輯:如果您想知道這個override關鍵字來自哪里,它是在 C++11 中介紹的。 由於我不知道您使用的是哪個 C++ 版本,我只想指出這一點。 您可以在此處閱讀有關覆蓋說明符的信息

編輯二:關於曾經的孩子 class 有自己的top_score ,您應該通過這些子類的構造函數進行設置。 像這樣:

class Job {
protected:
int top_score{0};
Job(top) : top_score(top) {}
...
};

class Waiter : public Job {
public:
  Waiter(int top): Job(top) {}
  ...
};

這樣每個孩子 class 都有自己的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();
  }
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM