- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有几个基类是我无法控制的:-
class BaseNode // Just a POD class. No VTable
{
void foo();
}
class BaseHost
{
public:
BaseNode *getNode()
{
...
}
}
我想“扩展”BaseNode::foo
的功能,但该类实际上是密封的。
建议如下:-
class MyNode: public BaseNode
{
void foo()
{
// do my stuff..., then
BaseNode::foo();
}
}
class MyHost: public BaseHost
{
public:
MyNode *getNode()
{
return (MyNode*) BaseHost::getNode(); // Slicing or UB risk?
}
}
如果 MyNode
引入额外的类成员或虚拟方法,事情就会变得很糟糕——但如果满足这些约束,我还有 UB 吗?
任何其他问题,或者我是否完全重新考虑设计?
最佳答案
这种向下转型要格外小心:它很容易导致 UB。
标准保证您可以安全地从 MyNode*
转换为 BaseNode*
:
4.10/3: A prvalue of type “pointer to cv D”, where D is a class type, can be converted to a prvalue of type “pointer to cv B”, where B is a base class of D. If B is an inaccessible or ambiguous base class of D, a program that necessitates this conversion is ill-formed. The result of the conversion is a pointer to the base class subobject of the derived class object. The null pointer value is converted to the null pointer value of the destination type.
但让我们玩火:标准还允许您在特定条件下从 BaseNode*
转换为 MyNode*
:
5.2.9/11: A prvalue of type “pointer to cv1 B,” where B is a class type, can be converted to a prvalue of type “pointer to cv2 D,” where D is a class derived from B, if a valid standard conversion from “pointer to D” to “pointer to B” exists, cv2 is the same cv-qualification as, or greater cv-qualification than, cv1, and B is neither a virtual base class of D nor a base class of a virtual base class of D. The null pointer value is converted to the null pointer value of the destination type. If the prvalue of type “pointer to cv1 B” points to a B that is actually a subobject of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the behavior is undefined
我尝试将这些引用翻译成纯文本:
BaseHost::getNode()
返回指向 MyNode
对象的向上转换指针,并且您的类层次结构中没有虚拟继承,那么它是好的。 BaseHost::getNode()
会返回其他东西(例如,指向普通 BaseNode
或 BaseNode
的另一个同级派生的指针>) 你将拥有 UB。 如前所述,这很危险:UB 可能已经在指针转换期间发生,甚至在您尝试取消引用指针之前。所以最好尽量避免它。如果你有一个多态的 BaseNode
类(例如,使用虚拟析构函数),你可以使用更安全的 dynamic_cast
.
关于c++ - 对象切片或 UB 风险?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38038122/
在回答中 Is it valid to create closure (lambda) objects using `std::bit_cast` in C++20? 表明程序可能具有未定义的行为“取
C++ 20 draft [concept.default.init] 没有精确定义 default_initializable template concept default_initializa
我担心这又是一个关于解释 ISO/IEC 14882(C++ 标准)的问题,但是: 正在从程序中调用 main,例如我从 main 递归调用 main() 至少不是实现定义的行为? (更新:我的意思是
想象一下: uint64_t x = *(uint64_t *)((unsigned char[8]){'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}); 我有 rea
考虑以下代码: int main() { typedef struct { int first; float second; } type; type whole = { 1, 2.0
这个问题已经有答案了: (Why) is using an uninitialized variable undefined behavior? (7 个回答) 已关闭 6 年前。 SO 上各种受人尊
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 6 年前。 Improve this ques
我最近在这样的代码中遇到了一个错误 class C { public: // foo return value depends on C's state // AND each cal
我最近在升级到 gcc 7.2 后遇到了一个奇怪的 C++ 崩溃,这可以使用以下简单的完整 c++11 程序来演示: #include #include struct MyObject {
所以,我一直在阅读 the C++ standard并来到 [defns.undefined](我正在阅读的 C++17 草案中的 3.27。请注意,虽然我在这里引用 C++17,但我在 other
这不是 Rvalue reference to lvalue reference 的拷贝 由于我是针对 C++17 提出这个问题的:由于悬空引用,以下是否仍会调用未定义的行为(当然,如果使用了引用)?
这个问题在这里已经有了答案: Arithmetic right shift gives bogus result? (2 个答案) 关闭 7 年前。 我想检查一些大的计算内存需求(存储在 unsig
坦率地说,这样的代码是否有效(除了缺乏必要的错误检查,为简单起见此处省略)? 通过互联网发送数据的代码: uint16_t i = htons(500); sendto(sockfd, &i, siz
我知道 C 和 C++ 以及不同的语言,但以下内容适用于两者。 TL/DR 我知道 i = i++; 是 UB,因为 i 在表达式中被修改了两次,而 C 和 C++ 禁止它。 引用资料: C99 6.
是否有可能满足以下条件的代码在每次运行相同输入时产生不同的输出? 虽然代码是单线程的它确实链接到一个线程安全的运行时库。 没有明确调用 rand() 或 time() 或它们的 friend 。 有一
这个问题在这里已经有了答案: is there issue will stringstream.str().c_str()? [duplicate] (3 个答案) 关闭 6 年前。 考虑以下代码,
根据 C++ 标准,如果对象本身不是 const,则可以从指针中丢弃 const 并写入对象。这样: const Type* object = new Type(); const_cast( ob
下面的代码会调用 UB 吗? int main(){ volatile int i = 0; volatile int* p = &i; int j = ++i * *p; } 最佳答案
这个问题在这里已经有了答案: will casting around sockaddr_storage and sockaddr_in break strict aliasing (2 个答案) 关
假设我们有来自 C++98 的遗留代码: bool expensiveCheck(); struct Foo; bool someFunc() { Foo *ptr = 0; if(
我是一名优秀的程序员,十分优秀!