使用对基类的引用访问派生类的私有成员函数

时间:2014-11-18 07:36:18

标签: c++ interface private-members

看看代码。我的界面看起来像这样:

class Abstract_base {
    public:
        virtual ~Abstract_base() {}

        virtual void f1 () = 0;
        virtual void f2 () = 0;
};

基类看起来像这样:

class Base : public Abstract_base {
    public:
        virtual ~Base() {}

        virtual void f1 () override { cout << "f1" << endl; }
        virtual void f2 () override { cout << "f2" << endl; }
};

我有两个派生类,如下所示:

class Derived_1 : public Base {
    public:
        virtual ~Derived_1() {}

    private:
        virtual void f2 () override { cout << "Derived_1::f2 ()" << endl; }

};

class Derived_2 : public Base {
    public:
        virtual ~Derived_2() {}

    private:
        virtual void f1 () override { cout << "Derived_2::f1 ()" << endl; }
};

最后我有Handler类,看起来像这样:

class Handler {
    public:
        Handler (Abstract_base& b) : base (b) {}
        virtual ~Handler() {}

        void process_1 () { 
            base.f1 ();
        }

        void process_2 () { 
            base.f2 ();
        }

    private:
        Abstract_base& base;
};

main.cpp看起来像这样:

int main (int argc, char** argv) {

    Derived_1 der1;
    der1.f2 ();

    Derived_2 der2;
    der2.f1 ();

    Handler handler1 (der1);
    handler1.process_2 ();

    Handler handler2 (der2);
    handler2.process_1 ();

    return 0;
}

当然代码不会编译,因为der1.f2()和der2.f1()是私有的,但如果我注释掉这两条指令并保留handler1.process_2()和handler2.process_1()指令,代码将编译并生成输出:

Derived_1::f2 ()
Derived_2::f1 ()

问题:

如何使用对Abstract_base类的引用来阻止调用这两个私有成员函数?我只是不希望用户有权访问Derived_1中的f2()和Derived_2中的f1()。

据我所知,我无法对Derived_1 :: f2()和Derived_2 :: f1()使用delete关键字。

你能建议我解决这个问题吗?

解决方案

我知道其中一个解决方案可能是让Handler成为这样的模板类:

template <class B>
class Handler_templ {
    public:
        Handler_templ (B& b) : base (b) { }
        virtual ~Handler_templ() {}

        void process_1 () { 
            base.f1 ();
        }

        void process_2 () { 
            base.f2 ();
        }

    private:
        B& base;
};

并像这样使用它:

Handler_templ<Derived_1> h1 (der1);
Handler_templ<Derived_2> h2 (der2);

h1.process_2 ();
h2.process_1 ();

令我惊讶的是为什么使用Handler类我可以调用这些私有成员函数?对于任何建议,我将非常感激。

此致 阿图尔

3 个答案:

答案 0 :(得分:1)

  

_&#34;如何使用对Abstract_base类的引用来阻止调用这两个私有成员函数?我只是不希望用户有权访问“Derived_2&#34; ._

f2()Derived_1中的f1()

通过派生类声明使用范围运算符,无法隐藏这些函数。

  

&#34;令我惊讶的是为什么使用Handler类我可以调用这些私有成员函数?&#34;

至于你的样品

class Base : public Abstract_base {
public:
    virtual ~Base() {}
    virtual void f1 () override { cout << "f1" << endl; }
    virtual void f2 () override { cout << "f2" << endl; }
};

class Derived_1 : public Base {
public:
    virtual ~Derived_1() {}
private:
    virtual void f2 () override { cout << "Derived_1::f2 ()" << endl; }
};

class Derived_2 : public Base {
public:
    virtual ~Derived_2() {}
private:
    virtual void f1 () override { cout << "Derived_2::f1 ()" << endl; }
};

使用派生类中的public函数覆盖private基类函数是完全可以的。
这些函数覆盖仍然可以通过Base / Abstract_base类接口显示。

private范围说明符使它们无法直接调用客户端。

答案 1 :(得分:1)

您无法使用对Abstract_base类的引用来阻止调用这两个私有成员函数。当您通过引用或基类的指针访问方法时,将不会考虑派生类的访问权限。 (编译器如何知道?)

根据Liskov替代原则(LSP),

  

使用指针或对基类的引用的函数必须能够   在不知情的情况下使用派生类的对象。

答案 2 :(得分:0)

你做不到。你不能阻止两件事:

Derived_1 der1;
((Abstract_base*)&der1)->f2 ();  // 1

指针或引用转换:

Derived_1 d;

Abstract_base* bp = &d; // 2
Abstract_base& ref = d; // 2

C ++没有提供停止转换基础指针/引用,或执行对象切片到基础的设置。 C ++都没有规定派生类必须在指定的保护级别中实现虚函数。