[英]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.