我有两个问题要问...
一个)
Class A{
int a;
public:
virtual void f(){}
};
Class B {
int b;
public:
virtual void f1(){}
};
Class C: public A, public B {
int c;
public:
virtual void f(){} // Virtual is optional here
virtual void f1(){} // Virtual is optional here
virtual void f2(){}
};
Class D: public C {
int d;
public:
void f2(){}
};
现在 C++ 说 C 的实例中不会有 3 个虚拟指针,而只有 2 个。然后,调用怎么可能说,
C* c = new D();
c->f2();
//由于f2()中定义的虚函数没有对应的虚指针。后期绑定(bind)是如何完成的?..
我看到说,这个函数的虚指针是加在C的第一个父类(super class)的虚指针中的。为什么会这样?..为什么没有虚表?...
大小(*c);//应该是 24 而不是 28.. 为什么?...
另外说,考虑到上面的代码,我这样做,
void (C::*a)() = &C::f;
void (C::*b)() = &C::f1;
printf("%u", a);
printf("%u",b);
// Both the above printf() statements print the same address. Why is that so ?...
// Now consider this,
C* c1 = new C();
c1->(*a)();
c1->(*b)();
//尽管 a 和 b 的地址相同,但调用的函数不同。这里函数的定义是如何界定的?...
希望我能尽快得到回复。
最佳答案
C++ 标准没有提及虚拟表,因此编译器可以自由选择任何方式对其进行优化。在这种情况下,它似乎已经合并了 C
的 vtable 与其中一个父表,但这当然不是必需的。 需要的是,如果您这样做:
C* c = new D();
c->f2();
它调用 D::f2
因为它在 C
中是虚拟的.
成员函数指针不允许转换为 void*
更不用说unsigned
因此,它们可能不会以预期的方式在 printf
中打印也就不足为奇了。 (它只是读取原始字节以打印出来)。原因是 %u
你在对 printf 撒谎,告诉它在你实际传递的参数完全不是 int
时打印一个 int .换句话说,a
和 b
成员函数指针实际上是不同的 printf
似乎在告诉你。由于它们确实不同,因此它们可以正常工作也就不足为奇了。
如果你想尝试打印编译器给你的真正的函数指针,“最可移植”的方法是 memcpy
它变成一个 vector unsigned char
然后打印出来。冗长的例子:
#include <iostream>
#include <vector>
class Foo
{
public:
virtual void f1() { }
virtual void f2() { }
void f3() { }
};
int main()
{
void (Foo::*a)() = &Foo::f1;
void (Foo::*b)() = &Foo::f2;
void (Foo::*c)() = &Foo::f3;
std::cout << a <<std::endl;
std::cout << sizeof(a) << std::endl;
std::cout << b <<std::endl;
std::cout << sizeof(b) << std::endl;
std::cout << c <<std::endl;
std::cout << sizeof(c) << std::endl;
std::vector<unsigned char> a_vec(sizeof(a));
memcpy(&a_vec[0], &a, sizeof(a));
for(size_t i = 0; i < sizeof(a); ++i)
{
std::cout << std::hex << static_cast<unsigned>(a_vec[i]) << " ";
}
std::cout << std::endl;
std::vector<unsigned char> b_vec(sizeof(b));
memcpy(&b_vec[0], &b, sizeof(b));
for(size_t i = 0; i < sizeof(b); ++i)
{
std::cout << std::hex << static_cast<unsigned>(b_vec[i]) << " ";
}
std::cout << std::endl;
std::vector<unsigned char> c_vec(sizeof(c));
memcpy(&c_vec[0], &c, sizeof(c));
for(size_t i = 0; i < sizeof(c); ++i)
{
std::cout << std::hex << static_cast<unsigned>(c_vec[i]) << " ";
}
std::cout << std::endl;
return 0;
}
在 g++ 4.2 上产生:
1
8
1
8
1
8
1 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0
c6 1d 5 8 0 0 0 0
而且你可以在这里清楚地看到所有三个成员函数指针都是不同的。
关于c++ - C++ 中的虚函数困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7650167/