这段禁止继承的代码是如何工作的?
我发现了一些相当奇怪的代码:
class Base {
public:
virtual bool IsDerived() const { return false; }
};
class Derived : public Base {
public:
bool IsDerived() const { return true; }
};
Derived* CastToDerived( Base* base )
{
// private and protected inheritance from Derived is prohibited
Derived* derived = dynamic_cast<Derived*>(base);
if( derived == 0 ) {
assert( !base->IsDerived() );
}
return derived;
}
我没有得到有关私有和受保护继承的段落。
假设我使用 protected
修饰符从 Derived
继承:
class FurtherDerived : protected Derived {
};
会发生什么?该断言将如何被触发?
I found some rather strange code:
class Base {
public:
virtual bool IsDerived() const { return false; }
};
class Derived : public Base {
public:
bool IsDerived() const { return true; }
};
Derived* CastToDerived( Base* base )
{
// private and protected inheritance from Derived is prohibited
Derived* derived = dynamic_cast<Derived*>(base);
if( derived == 0 ) {
assert( !base->IsDerived() );
}
return derived;
}
I don't get the passage about private and protected inheritance.
Suppose, I inherit from Derived
with protected
modifier:
class FurtherDerived : protected Derived {
};
What happens? How will that assert
get triggered?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您有
Protected
或Private
继承,您不能这样做:您也不能这样做,
这是因为,
Base
是Base
的不可访问的基础code>Derived由于您不能让Base
类指针指向Derived
类对象,因此该检查看起来是多余的。编辑:
即使您无法直接将
Derived
类对象分配给Base
类指针,也可能以其他方式发生这种情况,例如:如果Derived
的函数code> 类返回一个Base
类指针。简而言之,即使派生是受保护的或私有的,
Base
类指针也可能指向Derived
类对象。鉴于上述情况,
根据 C++ 标准:
5.2.7.8:
请注意,该标准明确要求推导必须公开。
因此,如果派生是受保护的或私有的,则
dynamic_cast
将检测到将转换视为不正确的转换,并返回NULL
(因为您使用的是指针)并且将调用assert
。所以是的,该代码非常有效。它确实做到了评论所说的
这个示例,演示了它按照评论工作:
If you have a
Protected
orPrivate
Inheritance, You cannot do:neither can you do,
This is because,
Base
is an inaccessible base ofDerived
Since you cannot have aBase
class pointer pointing toDerived
class object, that check looks redundant.EDIT:
Even if you cannot directly assign an
Derived
class object to anBase
class pointer, It can happen so in some other ways like: If a function ofDerived
class returns aBase
class pointer.In short, A
Base
class pointer may point to aDerived
class object even if derivation isprotected
orprivate
.Given the above,
As per C++ standard:
5.2.7.8:
Note that the standard specifically imposes the requirement of the derivation to be, Public.
Thus
dynamic_cast
will detect the treat the cast as an improper cast if derivation isprotected
orprivate
and return aNULL
(since you are using a pointer) and theassert
will be called.So Yes, the code is very much valid. And it indeed does what the comment says
This sample, demonstrates that it works as per the comments:
IsDerived
是在基类中定义的虚拟函数,函数根据调用该函数所使用的对象的静态类型进行解析。这意味着,这不是问题。它会起作用的。 (或者也许,我错过了你问题中的一些内容)。IsDerived
is a virtual function defined in the base class, and the functions are resolved based on the static type of the object using which you invoke the function. That means, that's not a problem. It will work. (Or maybe, I missed something in your question).dynamic_cast
执行运行时检查 (5.2.7/8)。如果
Base
被Derived
继承为受保护或私有,则运行时检查将失败。转换为指针时失败的运行时检查值为 NULL 指针 (5.2.7/9)。
因此,该代码是私有和受保护后代的解决方法:如果您使用
protected
或private
继承Derived
,则dynamic_cast
将返回 NULL 并且将执行自定义检查。dynamic_cast
performs run-time check (5.2.7/8).The runtime check will fail, if
Base
is inherited as protected or private byDerived
.The value of failed run-time check when casting to a pointer is a NULL pointer (5.2.7/9).
So, the code is a workaround for private and protected descendants: if you inherit
Derived
withprotected
orprivate
,dynamic_cast
will return NULL and the custom check will be performed.答案很简单。与许多其他注释一样,此注释不以任何方式、形状或形式描述代码。
示例:
使用多个版本的 gcc 和 clang 进行测试;他们都没有提出
assert
语句。附录
我怀疑发生的事情是,在具有特定编译器的特定机器上,相关代码确实以某种方式设法完成了作者认为它应该做的事情。我怀疑作者从未测试过这个所谓的检查,看看它是否真的像广告中那样有效。
The answer is simple. This comment like many, many other comments, is a comment that does not describe the code in any way, shape, or form.
Example:
Tested with multiple versions of gcc and clang; none of them raised that
assert
statement.Addendum
I suspect that what happened was that on some particular machine with some particular compiler, the code in question did somehow manage to do what the author thought it should do. I suspect that the author never tested this supposed check to see if it actually worked as advertised.