在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
Calling Derived class function from a Base class pointer after typecasting it to Derived class pointer
我对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;
}
我不确定,为什么以及如何d->B()
行工作?即使指针被类型转换为派生类,但基类对象本身不应该在内存中具有该函数。
我不确定,为什么 b->B(( 行是如何工作的?[..]基类对象本身不应在内存中具有该函数
你是对的!不行!
(好吧,函数不是存储在"内存中",但是...
调用无效。static_cast
说:"我保证这个Base*
指向一个Derived
"。这个承诺被打破了。
该程序具有未定义的行为。这在实践中可能意味着事情"看起来"在工作,特别是如果没有成员变量被不存在的函数触及......
当对象实际上不属于派生类型时,static_cast
派生类是未定义的行为。但未定义的行为意味着任何事情都可能发生,包括看似有效。(或者今天似乎有效,然后在最糟糕的时候失败了。
因此,从C++语言的角度来看,这就是官方解释的全部内容。
但至于为什么这可能适用于典型的真实编译器和计算机:成员函数的代码实际上并不存储在对象中,因为这将是很多字节。对于非虚函数,对象内部甚至没有任何指向函数的指针或类似的东西。相反,编译器将实现该函数Derived::B
本质上类似于非成员函数:
void __mangled_Derived_B(Derived const* this) { /*...*/ }
然后每次调用B
函数时,它都会传递正确的指针成为"this
"参数。
在您的示例中,Derived::B
实际上根本不使用this
,甚至没有隐式使用,因此不太可能出现问题。但是,如果它试图使用Derived
的数据成员,事情会变得更加危险,可能会导致奇怪的结果,对其他对象的更改或崩溃。
它无效。这是未定义的行为。
问题是编译器允许您编写此类代码。如果指向的对象实际上是Derived
,则从Base*
转换为Derived*
将是有效的。作为程序员,由您来确保它是有效的。
C++有很多情况下,你可以像这样在脚上开枪。它是语言的一部分。
越界访问、取消引用悬空指针/引用和无效强制转换,仅举几个最常见的
。- 为什么使用 "this" 指针调用派生成员函数?
- 如何使用基类指针引用派生类成员
- 使用基类指针创建对象时,缺少派生类析构函数
- 有没有一种"cleaner"的方法可以在指向基的指针向量中找到派生类的第一个实例?
- 如果基类包含双指针成员,则派生类的构造函数
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- 指向基类派生类的 std::unique_ptr 的指针
- 当我在 C++ 中将派生类的指针分配给指针时,地址会更改
- 从基指针到派生的强制转换问题
- 派生类是从基类继承 v 指针并仅使用它,还是也有自己的 v 指针?
- 从纯虚拟类 (A) 派生的指针无法访问来自纯类 (B) 的重载方法
- 如何模板化堆栈分配的多态指针数组到接口,包括派生类型的相应点?
- 从基类指针派生派生类的模板类型
- 指向从指针派生类成员函数的指针,指向基类成员函数
- 访问通过指针派生的类
- 如果未使用虚拟函数,则使用基类指针派生类的任何目的
- 从基指针C++派生类的类型
- 无法从指针派生类转换为指针基类(多态性)
- C++ - 传递智能指针派生类