簡體   English   中英

強制派生類實現私有方法

[英]Force derived class to implement a private method

有沒有辦法,我可以強制派生類通過私有函數實現接口。 我想要的是以下內容。

class base{
private:
    virtual void do_something() = 0; // This can be private/public/protected
};

派生類必須提供非公開的do_something()實現。 可以猜到,我的目的是使用戶實現一個函數,但要確保基類是調用該函數的class derived : public base{...} ,並且確保class derived : public base{...}的對象是class derived : public base{...}曾經無法單獨調用do_something()嗎?

編輯:只是想添加, class derived : baseclass derived : base將由用戶而不是我編寫。 用例是確保調用do_something()時基類的功能得到控制。

TL; DR:


特定

class base {
private:
    virtual void do_something() = 0;
};

您不能強制派生類將do_something實現為私有。 以下是合法的:

struct derived : base {
    void do_something() { ... }  // public
};

即使您可以強制將其私有,一個類也可以始終調用其自己的私有方法。 這與您的要求“ class derived : public base{...}的對象class derived : public base{...}將永遠無法自行調用do_something()do_something()


即使您可以強制派生類實現無法調用的方法,它們仍然可以像這樣解決:

struct derived2 : base {
    void do_something_impl() { .... }
private:
    void do_something() { do_something_impl(); }
};

現在,他們可以直接調用do_something_impl()

這個想法是,您可能需要派生類在構造函數調用中傳遞函數對象,而不是將do_something聲明為類成員。 但這是丑陋的-我寧願放棄對“無法從派生調用”的要求,並使用protected

#include <functional>
#include <iostream>

class base {
public:
  base(std::function<void()> do_something) : _do_something(do_something) {}
  void act() {
    _do_something();
  }

private:
  std::function<void()> _do_something;
};

class derived : public base {
public:
  derived() : base([&]{std::cout << "impl: " << prop1 << ", " << prop2 << std::endl;}) {}

private:
  int prop1;
  int prop2;
};

int main(int argc, char* argv[]) {
  derived d;
  d.act();
  return 0;
}

你不能那樣做。
請參閱@melpomene的不錯答案。


如果問題在於引用派生類的對象可以公開訪問,則可以執行以下操作:

class base {
private:
    virtual void do_something() = 0;
};

template<typename T>
class intermediate: public base, private T {
    void do_something() override {
        T::do_something();
    }
};

class derived {
public:
    void do_something() { }
};

int main() {
    auto *d = new intermediate<derived>{};
    base *b = d;
    // not allowed, it's private
    // d->do_somerhing();
    // b->do_something();
}

在特定限制內,您甚至可以模擬繼承的數據成員 (我知道,它們根本不是繼承的,但是朋友可以在這里提供幫助):

template<typename T>
class intermediate: public base, private T {
    friend T;

    void do_something() override {
        T::do_something(*this);
    }

private:
    int foo;
};

class derived {
public:
    void do_something(intermediate<derived> &ref) {
    ref.foo = 42;
    }
};

派生類無權訪問基類的private成員。 如果派生類必須重寫do_something() ,則應對其進行“保護”:

class base
{
protected:
    virtual void do_something() = 0;
};

如果do_something()必須是private ,則應聲明一個protected方法,該方法可以do_something()調用並且派生類將其覆蓋。 特別是在do_something()需要做其他事情時,派生類不應重寫。

class base
{
private:
    void do_something()
    {
        //...
        actually_do_something();
        //...
    }

protected:
    virtual void actually_do_something() = 0;
};

暫無
暫無

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

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