gpt4 book ai didi

c++ - 我认为下面的陈述不正确或者我遗漏了什么?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:46:15 25 4
gpt4 key购买 nike

以下段落摘自 Stroustup 书《The C++ Programming Language》(第三版)第 420 页:

Because a pointer to a virtual member (s in this example) is a kind of offset, it does not depend on an object’s location in memory. A pointer to a virtual member can therefore safely be passed between different address spaces as long as the same object layout is used in both. Like pointers to ordinary functions, pointers to nonvirtual member functions cannot be exchanged between address spaces.

我对本段的最后一句话提出异议。下面,您将找到一个代码片段,其中指向非虚拟成员函数的指针,foo()foo1(),在一个基数之间交换对象 a 和派生对象 b,没有问题。

不能做的是在派生类中重载基类中的任何函数,foo()foo1(),因为在这个在这种情况下,编译器将发出如下所示的错误。

#include <iostream>

class A
{
int i;
public:
A() : i(1) {}
void foo() { std::cout << i << '\n'; }
void foo1() { std::cout << 2 * i << '\n'; }
};

class B: public A
{
int j;
public:
B() : A(), j(2) {}
// void foo() { std::cout << j << '\n'; }
};

int main()
{
typedef void (A::* PMF)();
PMF p = &B::foo; // error C2374: 'p' redefinition, multiple initialization
// if foo() is overloaded in B.
PMF q = &B::foo1;
B b;
(b.*p)();
(b.*q)();

A a;
(a.*p)();
(a.*q)();
}

最佳答案

这句话是正确的:在(标准)C++ 中,一个程序,或者说进程,只有一个地址空间。因此,正如 ulidtko 所指出的,这句话指的是在不同进程的地址空间之间交换指向虚拟成员函数与非虚拟成员函数的指针的可能性。

一个类的非虚拟成员函数 几乎是一个标准函数,带有一个指向您调用它的对象的隐式参数(this 指针)。因此,它会在加载时在您的进程地址空间中分配一些地址。它在您的地址空间中的确切位置当然取决于您的平台以及该成员函数是否是动态链接库的一部分。关键是,对于两个进程,它不一定是相同的地址。因此,将指针传递给另一个进程然后在另一个进程中执行这样的函数可能会“让你的机器着火 (TM)”。

虚拟成员函数仍然与非虚拟成员函数非常相似,因为“执行时跳转到内存中的某个地址并将其传递给您的 this 指针”,但它是通过虚函数表 (vtable) 而不是直接调用的。因此,指向虚成员函数的指针几乎只是对象虚函数表的索引。调用该函数然后沿着“获取对象指针,可能增加指针以获取对象的 vtable 并跳转到该表的给定索引处的地址,将对象本身的地址作为 这个指针'。因此,这种通过 vtable 的间接寻址使得在地址空间之间交换指向虚拟成员函数的指针起作用。

免责声明:我有点倾向于“我真的知道我在说什么”——这里的舒适区。因此,如果我过度简化了某些事情或更糟的是,从事散布虚假信息,请随意撕碎我的答案;)。

关于c++ - 我认为下面的陈述不正确或者我遗漏了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15122953/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com