在 C++ 中是否可以强制显式向上转换
Is mandatory explicit upcasting possible in C++
假设 A
派生自 B
。有没有一种方法可以禁止像 B *x = new A()
中那样的隐式向上转换,例如通过显式强制转换?
这是不可能的,并且违反了多态性规则。
由于A派生自B,A是B。所以不需要强制转换,B是A的母亲class。A的任何实例都可以更改为B的实例。
这基本上就是您想要的,因为它允许针对接口进行编程。
通常,接口(尽管 C++ 中不存在接口)是通过某种抽象 class 定义的。如果您能够一直引用接口并远离某个接口的实际实现,代码通常会更好。
没有办法完全阻止这种转换。
您可以在大多数地方(但不是在 A
的朋友或成员中)使用私有继承,或者通过用包含或聚合关系替换继承(其中 A
包含一个实例)来阻止它或 pointer/reference 到 B
,而不是继承)。然后成员函数可以模拟显式转换:
B * x = new A(); // not allowed
A * a = new A(); // OK
B * b = a->to_B(); // OK
但是您应该考虑您真正想要防止的行为是什么,而不是让一个完全正常的操作需要跳过一个相当奇怪的圈套。几乎肯定有更好的方法来解决您的具体问题。
您可以为此创建一个包装器 class,例如:
template<typename T>
class MyPtr
{
public:
MyPtr(T* t) : t(t) {}
template <typename U>
MyPtr(U*) = delete;
MyPtr operator = (T* t) { this->t = t; return *this; }
template <typename U>
MyPtr operator = (U* t) = delete;
operator T* () const { return t; }
private:
T* t;
};
假设 A
派生自 B
。有没有一种方法可以禁止像 B *x = new A()
中那样的隐式向上转换,例如通过显式强制转换?
这是不可能的,并且违反了多态性规则。 由于A派生自B,A是B。所以不需要强制转换,B是A的母亲class。A的任何实例都可以更改为B的实例。
这基本上就是您想要的,因为它允许针对接口进行编程。 通常,接口(尽管 C++ 中不存在接口)是通过某种抽象 class 定义的。如果您能够一直引用接口并远离某个接口的实际实现,代码通常会更好。
没有办法完全阻止这种转换。
您可以在大多数地方(但不是在 A
的朋友或成员中)使用私有继承,或者通过用包含或聚合关系替换继承(其中 A
包含一个实例)来阻止它或 pointer/reference 到 B
,而不是继承)。然后成员函数可以模拟显式转换:
B * x = new A(); // not allowed
A * a = new A(); // OK
B * b = a->to_B(); // OK
但是您应该考虑您真正想要防止的行为是什么,而不是让一个完全正常的操作需要跳过一个相当奇怪的圈套。几乎肯定有更好的方法来解决您的具体问题。
您可以为此创建一个包装器 class,例如:
template<typename T>
class MyPtr
{
public:
MyPtr(T* t) : t(t) {}
template <typename U>
MyPtr(U*) = delete;
MyPtr operator = (T* t) { this->t = t; return *this; }
template <typename U>
MyPtr operator = (U* t) = delete;
operator T* () const { return t; }
private:
T* t;
};