我有一个基类,说Employee及其一些方法。稍后,我将派生一些子类,例如ManagerDeveloperDesigner等,它们也是雇员(由于继承)。现在说代码看起来像-

#include <iostream>
#include <vector>

class Employee{
    private : char name[5] = "abcd";
              void allDept(){ std::cout<<"Woo"; }

    public: void tellName(){std::cout << name << "\n"; }
            void showEveryDept(){std::cout<< "Employee can see every dept\n";
                                 allDept(); }
            virtual ~Employee() {}
};

class Manager: public Employee{
    private : char dept[5] = "aaaa";
    public: void showOwnDept(){std::cout<< "Manager can see own dept\n";}
};

class Designer: public Employee{
    private : char color = 'r';
    public: void showOwnDept(){std::cout<< "Designer can see own dept\n";}
};

int main(){

    Employee *E = new Designer;

    E->showEveryDept();

    // E->showOwnDept(); // will not work, but can be casted dynamically and even statically if sure, to call it!

    Designer* D = dynamic_cast<Designer*>(E);

    D->showOwnDept();
}

因此,我们在这里可以看到,我可以强制转换并使用多态性,将基类指针指向派生类对象,并仍然在子类上调用基类可访问方法。同样要从子类中调用子类方法,我可以动态地将其回退。

但是现在我要做的是,从子类调用中隐藏一个公共(public)类成员,以便子类无法调用它,而基类对象可以调用它。以showEveryDept()为例,它可以由子类和父类调用。但是,由于已经为Designer和Manager分配了他们的部门,因此我不希望他们使用此功能。

我尝试了一种非常拙劣的方式来解决此问题,方法是编写另一层b/w类Employee类,它是子类,例如
class Employee{
    private : char name[5] = "abcd";
              void allDept(){ std::cout<<"Woo"; }

    public: void tellName(){std::cout << name << "\n"; }
            void showEveryDept(){std::cout<< "Employee can see every dept\n";
                                 allDept();}
            virtual ~Employee() {}
};

class ELayer: private Employee{
    private: using Employee::showEveryDept;
    private: using Employee::tellName;
};

class Manager: public ELayer{
    private : char dept[5] = "aaaa";
    public: void showOwnDept(){std::cout<< "Manager can see own dept\n";}
};

class Designer: public ELayer{
    private : char color = 'r';
    public: void showOwnDept(){std::cout<< "Designer can see own dept\n";}
};

int main(){
    Employee *E = new Designer;
    E->showEveryDept();
    // E->showOwnDept(); // will not work, but can be casted dynamically
                      // and even statically if sure, to call it!
    Designer* D = dynamic_cast<Designer*>(E);
    D->showOwnDept();
}

但看起来很聪明,却行不通-



那么我在这里有什么选择?一种愚蠢的方法是使该函数成为虚函数,但子类也不会被强制重写它,并且如果他们忘记声明它,它将调用父函数吗?

最佳答案

另一个选择是在子级中使用using声明以及私有(private)继承来有选择地决定您可以从中访问什么。这比virtual替代方法更加灵活,并且没有任何额外的开销。另外,例如,它可以将公共(public)访问“转换”为 protected 访问。

class Employee
{
    private:
        char name[5] = "abcd";

        void allDept()
        {
            std::cout << "Woo";
        }

    public:
        void tellName()
        {
            std::cout << name << "\n";
        }

        void showEveryDept()
        {
            std::cout << "Employee can see every dept\n";
            allDept();
        }

        virtual ~Employee() {}
};

class Designer : private Employee
{
    private:
        char color = 'r';

    public:
        using Employee::tellName();

        void showOwnDept()
        {
            std::cout<< "Designer can see own dept\n";
        }
};

现在,您可以调用Desginer::tellName()Designer::showOwnDept(),但是Designer::showEveryDept()是私有(private)的!但是,缺点是您可能不再将Designer*从外部代码转换为Employee*。您可以在Employee中添加一个方法来做到这一点。但是,您应该记住在派生类中执行using Employee::as_employee
class Employee
{
    public:
        Employee& as_employee()
        {
            return *this;
        }

        const Employee& as_employee() const
        {
            return *this;
        }
};

无论如何,您应该问自己这是否真的是最理想的设计,并且确实需要这样做,或者在showDept()中仅具有一个(可选的)虚拟函数Employee来使派生类可以(或者必须这样做)会更好吗?纯)覆盖。

编辑:从我在另一个答案中读到的您的评论中,我可以轻松得出结论,您的问题是您不了解基类Employee不能用作某种“未分配的员工”占位符。这么说:设计师是雇员,未分配的雇员是雇员,但是设计师不是未分配的雇员。因此,最好是重组代码。无论如何,为了完整起见,我将保留上述解决方案。

关于c++ - 通过公共(public)继承仅公开某些方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39542917/

10-09 05:51
查看更多