将基类指针类型转换为派生类指针后,从基类指针调用派生类函数 我对C++(OOP)比较陌生。我正在努力理解以下代码: #include <iostream> class Base { public: Base() { std::cout << "In Base Constr: " << __FUNCSIG__ << std::endl; } virtual ~Base() { std::cout << "In Base Destr: " << __FUNCSIG__ << std::endl; } void A() { std::cout << "In Base func A " << __FUNCSIG__ << std::endl; } }; class Derived : public Base { public: Derived() { std::cout << "In Derived Constr: " << __FUNCSIG__ << std::endl; } ~Derived() { std::cout << "In Derived Destr: " << __FUNCSIG__ << std::endl; } void B() { std::cout << "In Derived func B " << __FUNCSIG__ << std::endl; } }; void test(Base* b) { Derived* d = static_cast<Derived*>(b); d->A(); d->B(); // How is this valid?? } int main() { Base *b = new Derived(); std::cout << "In main" << std::endl; b->A(); std::cout << __LINE__ << std::endl; Base *bb = new Base(); std::cout << __LINE__ << std::endl; test(bb); delete b; delete bb; } #包括 阶级基础{ 公众: Base(){ std::cout

将基类指针类型转换为派生类指针后,从基类指针调用派生类函数 我对C++(OOP)比较陌生。我正在努力理解以下代码: #include <iostream> class Base { public: Base() { std::cout << "In Base Constr: " << __FUNCSIG__ << std::endl; } virtual ~Base() { std::cout << "In Base Destr: " << __FUNCSIG__ << std::endl; } void A() { std::cout << "In Base func A " << __FUNCSIG__ << std::endl; } }; class Derived : public Base { public: Derived() { std::cout << "In Derived Constr: " << __FUNCSIG__ << std::endl; } ~Derived() { std::cout << "In Derived Destr: " << __FUNCSIG__ << std::endl; } void B() { std::cout << "In Derived func B " << __FUNCSIG__ << std::endl; } }; void test(Base* b) { Derived* d = static_cast<Derived*>(b); d->A(); d->B(); // How is this valid?? } int main() { Base *b = new Derived(); std::cout << "In main" << std::endl; b->A(); std::cout << __LINE__ << std::endl; Base *bb = new Base(); std::cout << __LINE__ << std::endl; test(bb); delete b; delete bb; } #包括 阶级基础{ 公众: Base(){ std::cout,c++,inheritance,polymorphism,downcast,static-cast,C++,Inheritance,Polymorphism,Downcast,Static Cast,它无效。它是未定义的行为 问题是编译器允许您编写这样的代码。如果指向的对象实际上是派生的,则从基*转换为派生的*将是有效的。这取决于作为程序员的您来确保它的有效性 C++中有很多情况下你可以这样踢自己的脚。这是语言的一部分。 越界访问、取消对悬空指针/引用的引用和无效强制转换以命名一些最常见的类型。当对象实际上不是派生类型时,对派生类进行静态强制转换是未定义的行为。但未定义的行为意味着任何事情都可能发生,包括看似有效。(或者今天看起来工作,然后在最糟糕的时候失败。) 从C++语言的观点来看,这就

它无效。它是未定义的行为

问题是编译器允许您编写这样的代码。如果指向的对象实际上是
派生的
,则从
基*
转换为
派生的*
将是有效的。这取决于作为程序员的您来确保它的有效性

C++中有很多情况下你可以这样踢自己的脚。这是语言的一部分。


越界访问、取消对悬空指针/引用的引用和无效强制转换以命名一些最常见的类型。

当对象实际上不是派生类型时,对派生类进行静态强制转换是未定义的行为。但未定义的行为意味着任何事情都可能发生,包括看似有效。(或者今天看起来工作,然后在最糟糕的时候失败。)

从C++语言的观点来看,这就是官方解释的全部内容。

但对于典型的真实编译器和计算机来说,这可能是可行的:成员函数的代码实际上并不存储在对象中,因为这将是大量字节。对于非虚拟函数,对象中甚至没有指向函数的指针或类似物。相反,编译器将实现该函数
派生::B
本质上类似于非成员函数:

void __mangled_Derived_B(Derived const* this) { /*...*/ }
然后每次调用
B
函数时,它都会传递正确的指针,成为“
this
”参数

在您的示例中,
Derived::B
实际上根本没有使用
this
,甚至没有隐式使用,因此不太可能出现问题。但如果它试图使用
Derived
的数据成员,事情会变得更加危险,可能会导致奇怪的结果、对其他对象的更改或崩溃

我不确定,为什么&b->b()行是如何工作的?[..]基类对象本身不应该在内存中有这个函数

你说得对!它不起作用

(嗯,函数不是存储在“内存”中,而是…)

调用无效。
static\u cast
表示“我保证此
Base*
指向一个
派生的
”。该承诺已被打破


程序有未定义的行为。这实际上意味着事情“看起来”正常运行,特别是当不存在的函数没有触及任何成员变量时…

@Gupta-您想到的是
dynamic\u cast
,这里的问题应该很好地解释它。我从未理解OOP为什么会变得多元化。