我试着强迫人们派生一个类重新实现一个函数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中的一个问题)?请记住,目标是阻止最终用户在派生类中调用默认版本。
答案 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 ++中是合法的,偶尔也是有用的。