更改派生类中函数的可见性
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()公开(这在ModelB中会是一个问题)的情况下,飞机中的派生类是否有可能调用fly(,的派生版本?请记住,目标是防止最终用户调用派生类中的默认版本。
这就是我理解您的问题的方式。您要求,如果您的派生类想要回退到基类中的实现,它必须明确声明。考虑这个解决方案。
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++中是合法的,偶尔也有用。
更改可见性很好,有时也是可取的。您的问题是将指针投射到受保护的基类。由于虚拟函数绑定较晚,编译器无法告知指针类型的实际可见性,重写也不会自动更改基类型中的可见性。
另一种方法是在Airplane之后有一个中间类,公开该方法。然后,您可以在需要的地方将其用作基指针类型。
相关文章:
- 如何更改唯一指针向量的可见性
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- 限制静态库中符号的可见性 (MSVC/Visual C++)
- 班级成员可见性C++
- 内联模板函数的可见性
- Clang 是否可以在使用可见性属性时生成导入库(不带 __declspec(dllexport))?
- std::mutex 的发布-获取可见性保证是否仅适用于关键部分?
- 符号可见性和 gcc 警告
- C++/libscreen 无法更新可见性
- 在 C++11 线程中,std::mutex 对内存可见性有什么保证?
- C++继承构造函数的可见性
- CRTP - 嵌套叶类类型的可见性
- C++模板 - 实例之间的通用操作和成员可见性
- 成员函数声明签名中的类成员可见性
- 派生模板类中基类构造函数的可见性
- C++11风格的SFINAE和模板实例化上的函数可见性
- 基类的复制构造函数的可见性问题
- 更改派生类中函数的可见性
- 函数重载在基类和派生类之间拆分的可见性
- 继承构造函数、默认构造函数和可见性