#include <iostream>
using namespace std;
class A
{
public:
static int a;
int b = 1;
void test()
{
cout << "called A\n";
}
};
int A::a = 10;
class B : public A
{
public:
void test()
{
cout << "called B\n";
}
};
int main()
{
cout << B::a << endl;
B* ptr_B = new B();
ptr_B -> test();
A* ptr_A = (A*)ptr_B;
ptr_A -> test();
cout << ptr_A << ' ' << ptr_B << endl;
return 0;
}
代码如上,自己有几个地方比较困惑。
1.为什么static变量不能就地初始化,c++11不是就已经允许其它变量可以就地初始化吗?
2.当实例化派生类的时候,调用了基类的构造函数,那是相当于有一个匿名的基类对象被构造了吗?还是不存在这样的一个匿名对象,只是基类构造的部分是作为派生类的一部分而存在的?
3.用派生类的指针和基类的指针,当它们都是指向派生类对象的地址的时候,调用同名函数,它们的底层机制是如何实现的?为什么即便指向的是相同的地址,但是它们调用的时候却可以调用不同的函数?编译器层面是如何解释的哦?
1. After C++11, static members can be initialized directly, but only for literal types.
2. To be precise, the member belonging to the base class is initialized. , are not anonymous, and these members are also part of the derived class.
3. This is a big problem. You can learn about the C++ object memory model and the virtual function calling mechanism. I can briefly introduce it to you:
(1) With virtual functions There is a hidden pointer member (vptr) in the class, which points to a virtual table (vtable) in a read-only area in the program.
(2) Classes with virtual functions will have a corresponding virtual table after compilation.
(3) This table stores the function address of the actual implementation of the virtual function in this class.
(4) When you call a virtual function of an object, the program will find the function that should actually be called from the vtable pointed to by its vptr.
1. Only member variables, static const variables and enum can be initialized in place. The reason why non-static cannot be initialized in place is according to Bjarne Stroustrup’s words:
2. As part of a derived class instance.
3. This should be considered separately between virtual functions and non-virtual functions. Your
test()
here is a non-virtual function, so v-table will not be searched. The corresponding implementation will be found according to the type definition of the variable; if it isvirtual
The method will be based on the corresponding method of the actual class of the object. At the compiler level, for your example here, it is simply equivalent tostd::bind(&B::test, ptr_B)();
andstd::bind(&A::test, ptr_A)();
, so the function implementation is of course different.