更改Derived类中函数的可见性

时间:2014-09-24 07:14:25

标签: c++ inheritance polymorphism

我试着强迫人们派生一个类重新实现一个函数foo(),但仍然提出一个必须明确调用的默认版本。重点是避免代码重复foo()的defalut版本而不让它“隐式”继承。

执行此操作的常用方法是创建纯虚拟公共foo(),然后创建受保护的foo_impl();并将foo_impl()调用到foo()重新实现中:

class Airplane {
public:
    virtual ~Airplane() {}
    virtual fly(int destination) = 0;       // function interface, public and pure virtual
protected:
    void fly_impl(int destination);         // not-virtual function implementation, declared protected
};                                          // to prevent people calling
                                            // Derived.Airplane::fly_impl();

void Airplane::fly_impl(int destination)    // Default implementation
{
    std::cout << "Flyed defaultly to " << destination << std::endl;
}

class ModelA: public Airplane {
public:
    virtual void fly(int destination)       // reimplementation of the pure virtual function fly
    {
        fly_impl(destination);              // explicit call to default implementation
    }
    virtual ~ModelA() {}
};

它有效,但它有点难看,所以我尝试了别的东西,并遇到了问题:

如果我在派生类中更改虚拟重新实现的函数的可见性,似乎多态性不起作用。我无法理解为什么,它是一个错误,它只是C ++的方式,还是我的错误?

代码是(例如来自Effective C ++并进行了一些修改):

class Airplane {
public:
    virtual ~Airplane() {}
protected:
    virtual void fly(int destination) = 0;  // function interface, declared protected
};                                          // to preventi people from calling
                                            // Derived.Airplace::fly();

void Airplane::fly(int destination)         // Default implementation
{
    std::cout << "Flyed defaultly to " << destination << std::endl;
}

class ModelA: public Airplane {
public:
    virtual void fly(int destination)       // reimplementation of the pure virtual function fly
    {                                       // this time it is public
        Airplane::fly(destination);         // explicit call to default implementation
    }
    virtual ~ModelA() {}
};

class ModelB: public Airplane {
public:
    virtual void fly(int destination)       // another reimplementation, public again
    {
        std::cout << "Flyed ModelBly to " << destination << std::endl;
    }
    virtual ~ModelB() {}
};

int main()
{
    ModelA A1;
    ModelB B1;

    ModelA* A2 = new ModelA();
    ModelB* B2 = new ModelB();

    Airplane* A3 = new ModelA();
    Airplane* B3 = new ModelB();

    A1.fly(1);
    B1.fly(2);

    A2->fly(3);
    B2->fly(4);

    A3->fly(5);                              // ERROR: fly() is protected in Airplane
    B3->fly(6);                              // ERROR: fly() is protected in Airplane
}

问题是:飞机上的衍生飞机类是否有可能调用fly()的衍生版本,而不会使Airplane :: fly()公开(这将是是ModelB中的一个问题)?请记住,目标是阻止最终用户在派生类中调用默认版本。

2 个答案:

答案 0 :(得分:0)

改变能见度很好,有时也是可取的。您的问题是您正在将指针转换为受保护的基类。由于虚函数的后期绑定,编译器无法判断指针类型的实际可见性,并且覆盖不会自动更改基类型的可见性。

另一种方法是在Airplane之后设置一个使该方法公开的中间类。然后,您可以在需要时将指针类型作为基础使用它。

答案 1 :(得分:0)

这就是我理解你的问题的方法。如果派生类想要回退到基类中的实现,则需要明确说明。考虑这个解决方案。

class Airplane {
public:
  virtual ~Airplane() {}
  virtual void fly(int destination) = 0; 
}; 

inline void Airplane::fly(int destination) // implement pure virtual function!
{
  std::cout << "Flyed defaultly to " << destination << std::endl;
}

class ModelA: public Airplane {
public:
  virtual void fly(int destination) { Airplane::fly(destination); }
  virtual ~ModelA() {}
};

这里的技巧是为纯虚函数提供主体。它在C ++中是合法的,偶尔也是有用的。