繁体   English   中英

更改函数在派生类中的可见性

[英]Change the visibility of a function in a Derived class

我正在尝试迫使派生类的人重新实现函数foo(),但仍提出必须显式调用的默认版本。 关键是要避免foo()的默认版本的代码重复,而不要让它“隐式”继承。

常用的方法是制作一个纯虚拟的公共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
}

问题是:飞机*中处理的飞机的派生类是否有可能在不公开Airplane :: fly()的情况下调用fly()的派生版本(这在ModelB中是个问题)? 请记住,这样做的目的是防止最终用户在派生类中调用默认版本。

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

一种替代方法是在Airplane之后设置一个中间类,以将该方法公开。 然后,可以在需要时将其用作基础指针类型。

这就是我理解您的问题的方式。 您要求,如果派生类希望回退到基类中的实现,则必须明确声明该实现。 考虑这个解决方案。

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 ++中,它是合法的,有时是有用的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM